├── enum.md ├── Dates ├── run_all.sh ├── dayOfYear.swift ├── yesterday.swift ├── tomorrow.swift ├── isLeapYear.swift ├── lastDayOfMonth.swift └── README.md ├── SwiftCookBook.playground ├── Pages │ ├── Concurrency.xcplaygroundpage │ │ └── Contents.swift │ ├── Sets.xcplaygroundpage │ │ └── Contents.swift │ ├── Dictionaries.xcplaygroundpage │ │ └── Contents.swift │ ├── Colors.xcplaygroundpage │ │ └── Contents.swift │ ├── Strings.xcplaygroundpage │ │ └── Contents.swift │ ├── Arrays.xcplaygroundpage │ │ └── Contents.swift │ └── Date_Time.xcplaygroundpage │ │ └── Contents.swift └── contents.xcplayground ├── function.md ├── color.md ├── sets.md ├── sorting.md ├── dictionary.md ├── README.md ├── functional.md ├── array.md ├── strings.md └── LICENSE /enum.md: -------------------------------------------------------------------------------- 1 | # Enumerations 2 | 3 | ## CaseIterable Protocol 4 | https://developer.apple.com/documentation/swift/caseiterable 5 | -------------------------------------------------------------------------------- /Dates/run_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | swift lastDayOfMonth.swift 3 | swift isLeapYear.swift 4 | swift tomorrow.swift 5 | swift yesterday.swift 6 | -------------------------------------------------------------------------------- /SwiftCookBook.playground/Pages/Concurrency.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | //: iOS Concurrency Playground 4 | 5 | import Foundation 6 | 7 | //: Async Queue 8 | 9 | //: Sync Queue 10 | 11 | //: [Next](@next) 12 | -------------------------------------------------------------------------------- /function.md: -------------------------------------------------------------------------------- 1 | ## Swift Functions 2 | 3 | 4 | ### Default Parameters 5 | 6 | ```swift 7 | 8 | ``` 9 | 10 | 11 | ### Variadic Parameters 12 | 13 | ```swift 14 | 15 | ``` 16 | 17 | 18 | ### Functions as Parameters 19 | 20 | ```swift 21 | 22 | ``` 23 | -------------------------------------------------------------------------------- /Dates/dayOfYear.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | func dayOfYear() -> Int { 4 | let date = Date() // now 5 | let calendar = Calendar.current 6 | 7 | let day = calendar.ordinality(of: .day, in: .year, for: date) 8 | 9 | return day! 10 | } 11 | 12 | let d = dayOfYear() 13 | print("Day Of Year: \(d)") -------------------------------------------------------------------------------- /Dates/yesterday.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | func yesterday() -> Date { 4 | 5 | var dateComponents = DateComponents() 6 | dateComponents.setValue(-1, for: .day) // -1 days 7 | 8 | let now = Date() 9 | let yesterday = Calendar.current.date(byAdding: dateComponents, to: now) 10 | return yesterday! 11 | } 12 | 13 | let aDate = yesterday() 14 | print("yesterday: \(aDate)") 15 | -------------------------------------------------------------------------------- /Dates/tomorrow.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /* 4 | swift tomorrow.swift 5 | */ 6 | func tomorrow() -> Date { 7 | 8 | var dateComponents = DateComponents() 9 | 10 | dateComponents.setValue(1, for: .day); 11 | 12 | let now = Date() 13 | let tomorrow = Calendar.current.date(byAdding: dateComponents, to: now) 14 | 15 | return tomorrow! 16 | } 17 | 18 | let aDate = tomorrow() 19 | print("tomorrow: \(aDate)") -------------------------------------------------------------------------------- /SwiftCookBook.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Dates/isLeapYear.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | func isLeapYear(_ year: Int) -> Bool { 4 | 5 | let isLeapYear = ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) 6 | 7 | 8 | return isLeapYear 9 | } 10 | 11 | func isLeapYear(date: Date = Date()) -> Bool { 12 | 13 | let calendar = Calendar.current 14 | let components = calendar.dateComponents([.year], from: date) 15 | 16 | let year = components.year 17 | return isLeapYear(year!) 18 | } 19 | 20 | let isY1900 = isLeapYear(1900) // false 21 | let isY2000 = isLeapYear(2000) // true 22 | let isY2015 = isLeapYear(2015) // false 23 | let isY2016 = isLeapYear(2016) // true 24 | let isY2020 = isLeapYear(2020) // true 25 | 26 | //let now0 = Date() 27 | //isLeapYear(now0) 28 | 29 | let isThisYear = isLeapYear() // Default parameter is Date() 30 | print("This year is a leap year: \(isThisYear)") 31 | -------------------------------------------------------------------------------- /SwiftCookBook.playground/Pages/Sets.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | //: Two ways to initialize 6 | var techTickerSet = Set() // Empty 7 | var financialTickerSet = Set(["GS", "MS", "BAC"]) 8 | 9 | for t in ["AAPL", "MSFT", "INTC", "GOOG"] { 10 | techTickerSet.insert(t) 11 | } 12 | 13 | let nameSet = Set(["Apple", "Microsoft", "Intel", "Alphabet"]) 14 | nameSet.first 15 | 16 | techTickerSet.count 17 | techTickerSet.contains("AAPL") 18 | 19 | //: Misc set operations 20 | 21 | techTickerSet.isDisjoint(with: financialTickerSet) 22 | var allTickers = techTickerSet.union(financialTickerSet) 23 | 24 | if !techTickerSet.contains("BBRY") { 25 | techTickerSet.insert("BBRY") 26 | } 27 | 28 | techTickerSet.contains("BBRY") 29 | techTickerSet.remove("BBRY") 30 | techTickerSet.contains("BBRY") 31 | 32 | allTickers.count 33 | allTickers.isSuperset(of: techTickerSet) 34 | techTickerSet.isSubset(of: allTickers) 35 | 36 | allTickers.removeAll() 37 | allTickers.isEmpty 38 | 39 | //: [Next](@next) 40 | -------------------------------------------------------------------------------- /Dates/lastDayOfMonth.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | func lastDayOfMonth(_ aDate:Date) -> Date { 4 | 5 | let calendar = Calendar(identifier: .gregorian) 6 | var components = calendar.dateComponents([.year , .month , .day], 7 | from:aDate) 8 | 9 | components.month = components.month! + 1 // Next month 10 | 11 | components.day = 0 // Set the day to zero to get last day of prior month 12 | 13 | let aDate = calendar.date(from: components) 14 | 15 | return aDate! 16 | } 17 | 18 | let now = Date() 19 | let day = lastDayOfMonth(now) 20 | 21 | print("Last day of this month: \(day)\n") 22 | 23 | /* 24 | Give a year, return the last day of each month 25 | */ 26 | func lastDayOfMonthList(year:Int) -> [Date] { 27 | 28 | var result:[Date] = [] 29 | 30 | var components = DateComponents() 31 | components.year = year 32 | components.day = 1 33 | 34 | for month in 1...12 { 35 | components.month = month 36 | 37 | let aDate = Calendar(identifier: .gregorian).date(from: components) 38 | 39 | let d = lastDayOfMonth(aDate!) 40 | result += [d] 41 | } 42 | return result 43 | } 44 | 45 | let x = lastDayOfMonthList(year: 2016) 46 | x.forEach({print("\($0)")}) 47 | -------------------------------------------------------------------------------- /SwiftCookBook.playground/Pages/Dictionaries.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | import Foundation 4 | 5 | //: Dictionary Creation 6 | var dictionary:[String:String] = [:] // Empty 7 | 8 | dictionary = ["AAPL": "Apple", 9 | "MSFT": "Microsoft", 10 | "ABC": "zzz", 11 | "GOOG": "Google"] 12 | 13 | let sharesOwned = ["AAPL": 200, "MSFT": 50] // [String:Int] 14 | 15 | //: Number of Elements (Keys) in Dictionary 16 | let n = dictionary.count 17 | n 18 | // Print value. Should wrap in let. See below 19 | let appleLongName = dictionary["AAPL"]! 20 | print("\(appleLongName)") 21 | 22 | //: Iterate over dictionary keys and values 23 | func dumpDictionary() { 24 | for (key, value) in dictionary { 25 | print("\(key), \(value)") 26 | } 27 | } 28 | dumpDictionary() 29 | 30 | //: Does Dictionary contain a key? 31 | //: Value might not exist so we wrap in let 32 | if let value = dictionary["AAPL"] { 33 | print("Found value for key = \(value)") 34 | } 35 | 36 | //: Add New Key/Value 37 | dictionary["GOOGL"] = "Alphabet" 38 | 39 | //: Get all keys 40 | dictionary.keys 41 | 42 | //: Remove Key/Value 43 | dictionary.removeValue(forKey: "GOOG") 44 | dictionary["AAPL"] = nil 45 | 46 | dictionary.count 47 | let sortedKeys = Array(dictionary.keys).sorted(by: <) 48 | 49 | //: Print, sorted by keys 50 | for (key, value) in dictionary.sorted(by: { $0.0 < $1.0 }) { 51 | 52 | // let value = dictionary[key] 53 | print("=>\(key), \(value)") 54 | } 55 | 56 | dictionary.updateValue("Alpha", forKey: "ALPHA") 57 | 58 | dumpDictionary() 59 | 60 | //: Remove All Dictionary Values 61 | dictionary.removeAll() 62 | 63 | //: Invert Key/Values 64 | 65 | //: Create UITableView Index 66 | 67 | //: [Next](@next) 68 | -------------------------------------------------------------------------------- /SwiftCookBook.playground/Pages/Colors.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | //: iOS Color Playground 4 | 5 | import UIKit 6 | 7 | /*: Standard UIColors 8 | black, blue, brown, clear, cyan, darkGray, gray, green, lightGray, magenta, orange, purple, red, white, yellow 9 | */ 10 | let blackColor = UIColor.black 11 | let whiteColor = UIColor.white 12 | let redColor = UIColor.red 13 | let blueColor = UIColor.blue 14 | let greenColor = UIColor.green 15 | let clearColor = UIColor.clear 16 | 17 | //: Standard CGColors - Core Graphics 18 | let blackCGColor = UIColor.black.cgColor 19 | let whiteCGColor = UIColor.white.cgColor 20 | let redCGColor = UIColor.red.cgColor 21 | let blueCGColor = UIColor.blue.cgColor 22 | let greenCGColor = UIColor.green.cgColor 23 | let clearCGColor = UIColor.clear.cgColor 24 | 25 | 26 | //: Gray 27 | 28 | let gray:CGFloat = 255.0 // 0=black to 255=white 29 | 30 | let aGrayColor = UIColor(red: gray/255.0, green:gray/255.0, blue:gray/255.0, alpha:1) 31 | 32 | 33 | //: rgba 34 | let color = UIColor(red: 200/255.0, green:100/255.0, blue:100/255.0, alpha:1) 35 | 36 | let cgColor = UIColor(red: 200/255.0, green:100/255.0, blue:100/255.0, alpha:1).cgColor // Use with Core Graphics 37 | 38 | var red, green,blue: CGFloat 39 | 40 | red = 100 41 | green = 225 42 | blue = 101 43 | 44 | UIColor(red: red/255.0, green:green/255.0, blue:blue/255.0, alpha:1) 45 | 46 | //: Hue 47 | 48 | let colorWithHue = UIColor(hue:0.625, saturation:0.0, brightness:0.85, alpha:1.0) 49 | 50 | //: Color from Pattern 51 | 52 | //let image = UIImage(named:"texture.png") 53 | //let colorPattern = UIColor(patternImage: image!) 54 | 55 | //if let image = UIImage(named:"texture.png") { 56 | // let colorPattern = UIColor(patternImage: image) 57 | //} 58 | 59 | 60 | //: [Next](@next) 61 | -------------------------------------------------------------------------------- /Dates/README.md: -------------------------------------------------------------------------------- 1 | [Basics](../README.md) | [Arrays](../array.md) | [Colors](../color.md) | [Date and Time](README.md) | [Dictionaries](../dictionary.md) | [Sets](../sets.md) | [Sorting](../sorting.md) | [Strings](../strings.md) | [Functional Swift](../functional.md) 2 | 3 | ## Swift Date Functions 4 | 5 | 6 | [Day of Year](#day-of-Year) | [Is Leap Year](#is-Leap-Year) | [Last Day Of Month](#last-Day-Of-Month) | [Tomorrow](#tomorrow) | [Yesterday](#yesterday) 7 | 8 | ### Day of Year 9 | Return the current day of the year. 10 | 11 | - Jan 1 returns 1 12 | - Feb 2 returns 32 13 | 14 | #### Example 15 | ```swift 16 | let d = dayOfYear() 17 | print("Day Of Year: \(d)") 18 | ``` 19 | 20 | [dayOfYear() Source](dayOfYear.swift) 21 | 22 | ### Last Day Of Month 23 | 24 | #### Example 25 | ```swift 26 | // Last day of current month 27 | let now = Date() 28 | let day = lastDayOfMonth(now) 29 | ``` 30 | 31 | ```swift 32 | // Last day of each month for given year 33 | let x = lastDayOfMonthList(year: 2016) 34 | x.forEach({print("\($0)")}) 35 | ``` 36 | 37 | > swift lastDayOfMonth.swift # run from shell 38 | 39 | [lastDayOfMonth() Source](lastDayOfMonth.swift) 40 | 41 | ### Is Leap Year 42 | 43 | #### Example 44 | 45 | ```swift 46 | let isY1900 = isLeapYear(1900) // false 47 | let isY2000 = isLeapYear(2000) // true 48 | let isY2015 = isLeapYear(2015) // false 49 | let isY2016 = isLeapYear(2016) // true 50 | let isY2020 = isLeapYear(2020) // true 51 | ``` 52 | #### Example 53 | ```swift 54 | let isThisYear = isLeapYear() // Default parameter is Date() 55 | print("This year is a leap year: \(isThisYear)") 56 | ``` 57 | 58 | > swift isLeapYear.swift 59 | 60 | [isLeapYear() Source](isLeapYear.swift) 61 | 62 | ### Tomorrow 63 | Calculate tomorrow's date 64 | 65 | > swift tomorrow.swift 66 | 67 | [tomorrow() Source](tomorrow.swift) 68 | 69 | ### Yesterday 70 | Calculate yesterday's date 71 | 72 | [yesterday() Source](yesterday.swift) 73 | 74 | -------------------------------------------------------------------------------- /color.md: -------------------------------------------------------------------------------- 1 | [Basics](README.md) | [Arrays](array.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 2 | 3 | ## Color 4 | 5 | ### Standard UIColors 6 | ```swift 7 | import UIKit 8 | 9 | /*: Standard UIColors 10 | black, blue, brown, clear, cyan, darkGray, gray, green, lightGray, magenta, orange, purple, red, white, yellow 11 | */ 12 | let blackColor = UIColor.black 13 | let whiteColor = UIColor.white 14 | let redColor = UIColor.red 15 | let blueColor = UIColor.blue 16 | let greenColor = UIColor.green 17 | let clearColor = UIColor.clear 18 | ``` 19 | 20 | ### Standard CGColors - Core Graphics 21 | 22 | ```swift 23 | let blackCGColor = UIColor.black.cgColor 24 | let whiteCGColor = UIColor.white.cgColor 25 | let redCGColor = UIColor.red.cgColor 26 | let blueCGColor = UIColor.blue.cgColor 27 | let greenCGColor = UIColor.green.cgColor 28 | let clearCGColor = UIColor.clear.cgColor 29 | ``` 30 | 31 | ### Gray 32 | 33 | ```swift 34 | let gray:CGFloat = 255.0 // 0=black to 255=white 35 | let aGrayColor = UIColor(red: gray/255.0, green:gray/255.0, blue:gray/255.0, alpha:1) 36 | ``` 37 | 38 | ### rgba 39 | 40 | ```swift 41 | let color = UIColor(red: 200/255.0, green:100/255.0, blue:100/255.0, alpha:1) 42 | 43 | let cgColor = UIColor(red: 200/255.0, green:100/255.0, blue:100/255.0, alpha:1).cgColor // Use with Core Graphics 44 | var red, green,blue: CGFloat 45 | 46 | red = 100 47 | green = 225 48 | blue = 101 49 | 50 | UIColor(red: red/255.0, green:green/255.0, blue:blue/255.0, alpha:1) 51 | ``` 52 | 53 | ### Hue 54 | 55 | ```swift 56 | let colorWithHue = UIColor(hue:0.625, saturation:0.0, brightness:0.85, alpha:1.0) 57 | ``` 58 | 59 | 60 | ### Color from Pattern 61 | 62 | ``` 63 | //let image = UIImage(named:"texture.png") 64 | //let colorPattern = UIColor(patternImage: image!) 65 | //if let image = UIImage(named:"texture.png") { 66 | // let colorPattern = UIColor(patternImage: image) 67 | //} 68 | ``` 69 | -------------------------------------------------------------------------------- /sets.md: -------------------------------------------------------------------------------- 1 | [Basics](README.md) | [Arrays](array.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 2 | 3 | ## Swift Sets 4 | 5 | 6 | ### Two ways to create 7 | 8 | ```swift 9 | var techTickerSet = Set() // Empty 10 | 11 | var financialTickerSet = Set(["GS", "MS", "BAC"]) 12 | 13 | 14 | ``` 15 | 16 | 17 | ### Add values to set 18 | 19 | ```swift 20 | for t in ["AAPL", "MSFT", "INTC", "GOOG"] { 21 | 22 | techTickerSet.insert(t) 23 | 24 | } 25 | ``` 26 | 27 | ### Insert Value if it is not in the set 28 | 29 | ```swift 30 | if !techTickerSet.contains("BBRY") { 31 | techTickerSet.insert("BBRY") 32 | } 33 | ``` 34 | 35 | 36 | ```swift 37 | let nameSet = Set(["Apple", "Microsoft", "Intel", "Alphabet"]) 38 | 39 | nameSet.first 40 | 41 | techTickerSet.count 42 | 43 | techTickerSet.contains("AAPL") 44 | ``` 45 | 46 | 47 | ### Number of elements in Set/Size 48 | 49 | ```swift 50 | allTickers.count 51 | ``` 52 | 53 | 54 | ### Is Set Empty 55 | 56 | ```swift 57 | allTickers.isEmpty 58 | ``` 59 | 60 | 61 | 62 | ### Set Contains Value 63 | 64 | ```swift 65 | techTickerSet.contains("BBRY") 66 | ``` 67 | 68 | ### Remove Element 69 | 70 | ```swift 71 | techTickerSet.remove("BBRY") 72 | ``` 73 | 74 | ### Disjoint Set 75 | 76 | ```swift 77 | techTickerSet.isDisjoint(with: financialTickerSet) 78 | ``` 79 | 80 | 81 | ### Set Union 82 | 83 | ```swift 84 | var allTickers = techTickerSet.union(financialTickerSet) 85 | 86 | let all = set1 + set2 + set3 87 | ``` 88 | 89 | 90 | ### Set Intersection 91 | 92 | ```swift 93 | let intersect = aSet1.intersection(aSet2) 94 | ``` 95 | 96 | 97 | ### Superset and Subset 98 | 99 | ```swift 100 | 101 | allTickers.isSuperset(of: techTickerSet) 102 | 103 | techTickerSet.isSubset(of: allTickers) 104 | ``` 105 | 106 | 107 | ### Remove All Elements 108 | 109 | ```swift 110 | allTickers.removeAll() 111 | 112 | ``` 113 | -------------------------------------------------------------------------------- /sorting.md: -------------------------------------------------------------------------------- 1 | [Basics](README.md) | [Arrays](array.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 2 | 3 | ## Sorting 4 | 5 | ```swift 6 | let companies = ["Microsoft", "Google", "Apple", "Amazon", "Intel"].sorted() 7 | 8 | let reversed = companies.sorted(by: {$1 < $0}) 9 | 10 | let reversedNames = companies.sorted(by: >) // even simpler reverse 11 | 12 | ``` 13 | 14 | ### 15 | ### Sort by Word Length 16 | 17 | ```swift 18 | // longest words first: ["orange","black", "white", "blue", "red"] 19 | ["red", "orange", "blue", "black", "white"].sorted(by: {$0.count > $1.count}) 20 | ``` 21 | 22 | ### Sort Classes 23 | 24 | ```swift 25 | /* 26 | Comparable: Equality == 27 | Comparable: < for sorted 28 | CustomStringConvertible: Provide description variable for print() 29 | 30 | Could use value type struct: 31 | struct Person: Equatable, Comparable, CustomStringConvertible {} 32 | 33 | */ 34 | public class Person: Equatable, Comparable, CustomStringConvertible { 35 | 36 | let first:String 37 | let last:String 38 | public var description:String { "\(first) \(last)" } 39 | 40 | init(first:String, last:String) { 41 | self.first = first 42 | self.last = last 43 | } 44 | 45 | 46 | public static func == (lhs: Person, rhs: Person) -> Bool { 47 | lhs.first == rhs.first && lhs.last == rhs.last 48 | } 49 | 50 | public static func < (lhs: Person, rhs: Person) -> Bool { 51 | if lhs.last != rhs.last { 52 | return lhs.last < rhs.last 53 | } 54 | return lhs.first < rhs.first 55 | } 56 | } 57 | 58 | let mathematicians = [Person(first: "Isaac", last: "Newton"), 59 | Person(first: "Blaise", last: "Pascal"), 60 | Person(first: "Daniel", last: "Bernoulli"), 61 | Person(first: "Pierre-Simon", last: "Laplace"), 62 | Person(first: "Johann", last: "Bernoulli"), 63 | 64 | ] 65 | 66 | let sortedMath = mathematicians.sorted() 67 | for w in sortedMath { 68 | print("\(w)") 69 | 70 | } 71 | ``` 72 | 73 | ### 74 | 75 | ```swift 76 | 77 | ``` 78 | 79 | ### 80 | 81 | ```swift 82 | 83 | ``` 84 | 85 | -------------------------------------------------------------------------------- /dictionary.md: -------------------------------------------------------------------------------- 1 | [Basics](README.md) | [Arrays](array.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 2 | 3 | ## Swift Dictionaries/Hash Maps 4 | 5 | ### Dictionary Creation 6 | 7 | ```swift 8 | var dictionary:[String:String] = [:] // Empty 9 | 10 | dictionary = ["AAPL": "Apple", 11 | "MSFT": "Microsoft", 12 | "AMZN": "Amazon", 13 | "GOOG": "Google"] 14 | 15 | let sharesOwned = ["AAPL": 200, "MSFT": 50] // [String:Int] 16 | ``` 17 | 18 | 19 | ### Number of Elements (Keys) in Dictionary 20 | 21 | ```swift 22 | let n = dictionary.count 23 | ``` 24 | 25 | 26 | ### Print value. Should wrap in let. See below 27 | 28 | ```swift 29 | let appleLongName = dictionary["AAPL"]! 30 | 31 | print("\(appleLongName)") 32 | 33 | ``` 34 | 35 | 36 | ### Iterate over dictionary keys and values 37 | 38 | ```swift 39 | func dumpDictionary() { 40 | 41 | for (key, value) in dictionary { 42 | print("\(key), \(value)") 43 | } 44 | } 45 | 46 | dumpDictionary() 47 | ``` 48 | 49 | 50 | 51 | ### Does Dictionary contain a key? 52 | 53 | Value might not exist so we wrap in let 54 | 55 | ```swift 56 | if let value = dictionary["AAPL"] { 57 | print("Found value for key = \(value)") 58 | } else { 59 | dictionary["AAPL"] = "Apple" // Add 60 | } 61 | 62 | ``` 63 | 64 | ```swift 65 | if dictionary["AAPL"] == nil { 66 | dictionary["AAPL"] = "Apple" 67 | } 68 | ``` 69 | 70 | ### Add New Key/Value 71 | 72 | ```swift 73 | dictionary["GOOGL"] = "Alphabet" 74 | ``` 75 | 76 | 77 | 78 | ### Get all keys 79 | 80 | ```swift 81 | dictionary.keys 82 | ``` 83 | 84 | 85 | 86 | ### Remove Key/Value 87 | 88 | ```swift 89 | dictionary.removeValue(forKey: "GOOG") 90 | 91 | dictionary["AAPL"] = nil 92 | 93 | dictionary.count 94 | 95 | let sortedKeys = Array(dictionary.keys).sorted(by: <) 96 | ``` 97 | 98 | 99 | 100 | ### Print, sorted by keys 101 | 102 | ```swift 103 | for (key, value) in dictionary.sorted(by: { $0.0 < $1.0 }) { 104 | 105 | // let value = dictionary[key] 106 | 107 | print("=>\(key), \(value)") 108 | 109 | } 110 | ``` 111 | 112 | 113 | ```swift 114 | dictionary.updateValue("Alpha", forKey: "ALPHA") 115 | 116 | dumpDictionary() 117 | ``` 118 | 119 | ### Remove All Dictionary Values 120 | 121 | ```swift 122 | dictionary.removeAll() 123 | ``` 124 | 125 | 126 | 127 | ### Invert Key/Values 128 | 129 | ```swift 130 | 131 | ``` 132 | 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # h4labs Swift Cookbook 2 | 3 | This content will (eventually) be mirrored on my site: http://www.h4labs.com/dev/ios/swift_cookbook.html 4 | 5 | This repo will be mainly about the Swift language. I have another [repo with small iOS projects](https://github.com/melling/ios_topics/blob/master/README.md) 6 | 7 | Swift 5.x compatible 8 | 9 | - [Basics](README.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 10 | - Collections: [Arrays](array.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | 11 | 12 | ## Variable Declarations 13 | 14 | Common types: **Int**, **String**, **Bool**, **CGFloat**, **Double**, **Float** 15 | 16 | **let** is used to declare immutable values, while **var** is used to declare mutable variables. 17 | 18 | ```swift 19 | let language = "Swift" // Immutable String 20 | var i = 0 // mutable Int 21 | i += 1 22 | var x:CGFloat = 2 23 | var name:String 24 | let max:Int 25 | max = 99 26 | var isDone = false // Bool 27 | ``` 28 | 29 | ## if 30 | 31 | ```swift 32 | let fuel = 9 33 | let msg:String // Must assign in all cases 34 | 35 | if fuel < 10 { 36 | msg = "Fuel dangerously low: \(fuel)" 37 | } else if fuel < 50 { 38 | msg = "Fuel low: \(fuel)" 39 | } else { 40 | msg = "Fuel OK" 41 | } 42 | ``` 43 | 44 | ## ternary operator 45 | 46 | ```swift 47 | let color = Bool.random() ? "red" : "black" 48 | ``` 49 | 50 | ## switch 51 | 52 | ```swift 53 | 54 | switch ticker { 55 | 56 | case "AAPL": 57 | 58 | case "GOOGL": 59 | 60 | case "MSFT": 61 | 62 | default: 63 | 64 | } 65 | 66 | ``` 67 | 68 | ## for 69 | 70 | ```swift 71 | for i in 0..<10 { 72 | print("\(i)") 73 | } 74 | 75 | for i in 0...9 { 76 | print("\(i)") 77 | } 78 | ``` 79 | 80 | ## for enumeration 81 | 82 | ```swift 83 | for company in ["Apple", "Google", "Microsoft"] { 84 | print("\(company)") 85 | } 86 | ``` 87 | 88 | ## function declarations 89 | 90 | ```swift 91 | func add1(i:Int) -> Int { i + 1 } // return word not needed if we have 1 expression 92 | let r0 = add1(i: 1) // 2 93 | ``` 94 | 95 | Same function but add _ to not need a named parameter 96 | 97 | ```swift 98 | func add1(_ i:Int) -> Int { i + 1 } // return word not needed if we have 1 expression 99 | let r0 = add1(1) // 2 100 | ``` 101 | 102 | 103 | ```swift 104 | 105 | ``` 106 | ### Multiple return values using tuples 107 | 108 | ```swift 109 | func bestLanguage() -> (String, Int) { 110 | return ("Swift", 1) 111 | } 112 | 113 | let (language, rank) = bestLanguage() 114 | ``` 115 | 116 | ## Randomness 117 | 118 | ```swift 119 | let rnd = Int.random(in: 0...1) // 0 or 1 120 | Bool.random() // true or false 121 | 122 | Int.random(in: 20...29) // Random in range 20 through 29 123 | Float.random(in: 0...1) // Random between 0 and 1 124 | 125 | [1,2,3].randomElement() // random Array element 126 | Set([1,2,3]).randomElement() // random Set element 127 | ``` 128 | 129 | ### Shuffle 130 | 131 | Sometimes, it's better to shuffle an Array then simply iterate of the result to get a random element. This allows each element to be chosen at random exactly once. 132 | 133 | ```swift 134 | let shuffled = [1,2,3].shuffled() 135 | ``` 136 | ## enum 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /functional.md: -------------------------------------------------------------------------------- 1 | [Basics](README.md) | [Arrays](array.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 2 | 3 | ## Functional Swift 4 | 5 | ### map 6 | 7 | ```swift 8 | [1,2,3].map {$0 * 2} 9 | 10 | let row = "id first last" 11 | let csv = String(row.map {$0 == " " ? "," : $0}) // replace all occurrences 12 | let xs:[Int] = stride(from: -100, to: 110, by: 10).map {$0} // [-100, -90, -80, ..., 100] 13 | ``` 14 | [map(_:)](https://developer.apple.com/documentation/swift/sequence/3018373-map) 15 | 16 | 17 | ### filter 18 | 19 | ```swift 20 | let evens = [1,2,3,4,5,6,7,8,9].filter {$0 % 2 == 0} // isEven 21 | ["5", "a", "6","b"].filter {($0 as Character).isNumber} 22 | ``` 23 | 24 | [filter(_:)](https://developer.apple.com/documentation/swift/sequence/3018365-filter) 25 | 26 | 27 | ### forEach 28 | 29 | ```swift 30 | [pronounView, answerWellView, answerConjugationView].forEach (view.addSubview) 31 | ``` 32 | 33 | [forEach(_:)](https://developer.apple.com/documentation/swift/array/1689783-foreach) 34 | 35 | 36 | ### reduce 37 | 38 | ```swift 39 | let sum = [1,2,3].reduce(0, +) 40 | let product = [1,2,3].reduce(1, *) 41 | ``` 42 | 43 | [reduce(_:_:)](https://developer.apple.com/documentation/swift/sequence/2907677-reduce) | [reduce(into:_:)](https://developer.apple.com/documentation/swift/array/3126956-reduce) 44 | 45 | 46 | ### flatMap, compactMap 47 | 48 | flatMap has been deprecated in Swift, use compactMap. 49 | 50 | ```swift 51 | ["55", "a", "6","b"].compactMap {Int($0)} 52 | ``` 53 | 54 | [compactMap(_:)](https://developer.apple.com/documentation/swift/sequence/2950916-compactmap) 55 | 56 | 57 | ### take 58 | 59 | 60 | ```swift 61 | [1,2,3,4,5,6,7,8,9].prefix(3) 62 | ``` 63 | 64 | If you wanted to have your own **take** extension on Array, you could add something like the following: 65 | 66 | ```swift 67 | extension Array { 68 | func take(_ n: Int) -> ArraySlice { 69 | self[0.. 0} ) 85 | ``` 86 | 87 | [prefix(while:)](https://developer.apple.com/documentation/swift/sequence/3128810-prefix) 88 | 89 | ### drop/dropWhile 90 | 91 | ```swift 92 | let xs = [1,2,3] + [4,5,6] 93 | let test = (0...3).drop { $0 > 1 } //dropWhile 94 | 95 | xs.drop { $0 <= 3 } 96 | //[1,2,3,4,5,6].drop(while: 2) 97 | [1,2,3,4,5,6].dropFirst(3) 98 | [1,2,3,4,5,6].dropFirst() // defaults to 1 99 | 100 | [1,2,3,4,5,6].dropLast() // defaults to 1 101 | 102 | ``` 103 | 104 | [drop(while:)](https://developer.apple.com/documentation/swift/sequence/3128801-drop) | [dropFirst(_:)](https://developer.apple.com/documentation/swift/sequence/3128803-dropfirst) | [dropLast(_:)](https://developer.apple.com/documentation/swift/sequence/3128805-droplast) 105 | 106 | ### zip 107 | 108 | ```swift 109 | let companies = ["Apple", "Google", "Microsoft"] 110 | let tickers = ["AAPL", "GOOGL","MSFT"] 111 | 112 | for (ticker, company) in zip(tickers, companies) { 113 | print("\(ticker),\(company)") 114 | } 115 | ``` 116 | 117 | - [zip(_:_:)](https://developer.apple.com/documentation/swift/1541125-zip) 118 | 119 | 120 | ### Combining 121 | 122 | ```swift 123 | [1,2,3,4,5,6,7,8,9].filter {$0 % 2 == 0}.map {$0 * 2}.reduce(0, +) 124 | ["550", "a", "6", "b", "42", "99", "100"].compactMap {Int($0)}.filter {$0 < 100} 125 | ``` 126 | -------------------------------------------------------------------------------- /SwiftCookBook.playground/Pages/Strings.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | 3 | /*: 4 | A Cookbook of Swift String functions 5 | 6 | Copy and Paste into a Swift Playground 7 | Version: 20151019.01 8 | 9 | Some ideas came from [Perl](http://pleac.sourceforge.net/pleac_perl/strings.html) and [Python](http://pleac.sourceforge.net/pleac_python/strings.html) Pleacs 10 | */ 11 | import Foundation 12 | 13 | //: String Introduction 14 | var mystr:String // Mutable string 15 | 16 | mystr = "\n" // a newline character 17 | let s1 = "\\n" // Two characters, \ and n 18 | let bear = "🐻" 19 | 20 | for character in s1.characters { 21 | var s0 = ":" 22 | s0.append(character) 23 | print(s0) 24 | } 25 | 26 | mystr = "Jon \"Maddog\" Orwant" // escaped double quote 27 | var str = "Hello, playground" // Mutable string 28 | let language = "Swift" // Immutable string 29 | 30 | 31 | 32 | var str1: String 33 | var str2: String = "hello world" 34 | 35 | //: String Length 36 | 37 | let stringLength = str.characters.count 38 | 39 | //: String Equality 40 | 41 | if str == "Hello, playground" { 42 | print("Strings are Equal") 43 | } 44 | 45 | //: Case Insensitive Comparison 46 | 47 | let nativeLanguage = "French" 48 | if nativeLanguage.caseInsensitiveCompare("french") == .orderedSame { // NSComparisonResult.OrderedSame 49 | print("Strings are equal") 50 | } 51 | 52 | 53 | //: String Inequality 54 | 55 | if str != "Hello world" { 56 | print("Strings are NOT Equal") 57 | } 58 | 59 | //: Test for Empty String 60 | var aString = "" 61 | if aString.isEmpty { 62 | print("String is empty") 63 | } 64 | 65 | 66 | //: Concatenate 67 | 68 | str1 = "Hello, " 69 | str2 = "playground" 70 | 71 | str = str1 + str2 // Swift's concatenate operation 72 | str = "\(str1)\(str2)" // Using String interpolation 73 | 74 | //: Append string 75 | 76 | str = "hello" 77 | str += " world" 78 | 79 | //: Append a single character 80 | 81 | let period: Character = "." 82 | str.append(period) 83 | 84 | //: Prepend string 85 | 86 | _ = "My \(str)" // Ignoring result 87 | _ = "My " + str 88 | 89 | //: Simple CSV split 90 | let csv = "one,two,3" 91 | 92 | let anArray = csv.components(separatedBy: ",") 93 | print(anArray) 94 | 95 | //: Join string to CSV 96 | anArray.joined(separator: ",") 97 | //: String Contains a Substring 98 | 99 | str = "www" 100 | let url = "https://www.h4labs.com/" 101 | 102 | if url.contains(str) { 103 | print("Contains string: \(str)") 104 | } 105 | 106 | //: String begins with/Has prefix 107 | 108 | url.hasPrefix("https:") 109 | 110 | //: String ends with/Has suffix 111 | url.hasSuffix("/") 112 | 113 | //: String to Letter Array 114 | var letters:[String] = [] 115 | "horse".characters.forEach {letters.append(String($0))} 116 | letters 117 | 118 | //: Trim White Space 119 | 120 | var blogTitle = " Swift Cookbook ".trimmingCharacters(in: NSCharacterSet.whitespaces) 121 | 122 | //stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) 123 | 124 | //: Also remove newlines 125 | blogTitle = " Swift Cookbook \n".trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) 126 | //: Remove surrounding quotes 127 | let quotedString = "\"h4labs\"" 128 | 129 | let quotesRemoved = quotedString.replacingOccurrences(of: "\"", with: "") 130 | 131 | //: Uppercase 132 | 133 | var company = "apple computer" 134 | company = company.uppercased() 135 | 136 | //: Capitalize/Title case 137 | 138 | company = company.capitalized// capitalize every word 139 | company = company.localizedCapitalized // capitalize every word localized 140 | 141 | 142 | //: Lowercase 143 | 144 | company = company.lowercased() 145 | 146 | //: Loop Over Ever Character of String 147 | for character in "hello world".characters { 148 | print(character) 149 | } 150 | 151 | //: String to Int 152 | let aNumberStr = "10" 153 | let anInt: Int? = Int(aNumberStr) 154 | 155 | //: String to Double 156 | let aDouble: Double? = Double(aNumberStr) 157 | 158 | //: First letter 159 | let aWord = "hello" 160 | let firstLetter = aWord.characters.first 161 | let lastLetter = aWord.characters.last 162 | let x = aWord.characters.prefix(3) 163 | String(x) 164 | 165 | //: [Next](@next) 166 | -------------------------------------------------------------------------------- /SwiftCookBook.playground/Pages/Arrays.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | //: [Previous](@previous) 2 | /*: 3 | Swift Cookbook Array Functions 4 | Copy and Paste into a Swift Playground 5 | Version: 20151019.01 6 | 7 | Some ideas came from [Perl](http://pleac.sourceforge.net/pleac_perl/arrays.html) and [Python](http://pleac.sourceforge.net/pleac_python/arrays.html) Pleacs 8 | */ 9 | import Foundation 10 | 11 | //: Array Creation 12 | var anArray = ["one", "two", "three","one"] // Mutable 13 | let anImmutableArray = ["four", "five"] // Immutable 14 | let numbers = Array(1...10) // 1 through 10 15 | let numbers9 = Array(1..<10) // 1 through 9 16 | let numbers0_9 = [Int](0..<10) 17 | //let total = numbers0_9.reduce(0, +) 18 | 19 | let multDim:[[Int]] = [[1,2,3], [4,5,6], [7,8,9]] 20 | 21 | //: First element of array 22 | anArray.first // a Swift solution. nil if empty 23 | anArray[0] // Classic solution. Error if empty 24 | 25 | //: Last element of array 26 | anArray.last // a Swift solution. nil if empty 27 | anArray[anArray.count-1] // Classic solution. Error if empty 28 | 29 | //: Empty Array 30 | 31 | var emptyArray:[String] = [] 32 | if emptyArray.isEmpty { 33 | print("Empty Array") 34 | } 35 | 36 | emptyArray.first // Returns nil 37 | emptyArray.last // Returns nil 38 | 39 | 40 | //: Does value exist in array? 41 | if anArray.contains("three") { 42 | print("Array contains value") 43 | } 44 | 45 | //: How to filter array to get unique items? 46 | // Create a Set then build array from it. Set guarantees uniqueness 47 | var aSet:Set = [] 48 | anArray.forEach{aSet.insert($0)} // Could do this: aSet = Set(anArray) 49 | aSet.count 50 | anArray = Array(aSet) 51 | anArray.count 52 | 53 | //: How to merge arrays? 54 | // Just like prior solution. Uses Set's union function 55 | // Also skip closure 56 | 57 | anArray = ["one", "two", "three","one"] 58 | aSet = Set(anArray) 59 | aSet.formUnion(anImmutableArray) 60 | aSet.count 61 | anArray = Array(aSet) 62 | anArray.count 63 | 64 | //: Sort Array 65 | anArray = ["one", "two", "three","one"] 66 | let sortedArray = anArray.sorted() // Returns a new sorted array 67 | let sortedArrayReverse = anArray.sorted(by: >) // Reverse order 68 | 69 | sortedArray 70 | sortedArrayReverse 71 | anArray 72 | 73 | anArray.sort() // Update the array in place 74 | anArray 75 | anArray.removeLast() 76 | anArray.removeFirst() 77 | 78 | //: Find the index of an element in an Array 79 | anArray = ["one", "two", "three","one"] 80 | 81 | anArray.index(of: "two") 82 | 83 | //: indexOf() can also be used to search an array 84 | let aNumericArray = [1, 2, 10, 20, 100] 85 | let x = aNumericArray.index(where: {$0 > 10}) // Find the index of first value greater than 10 86 | print(x ?? 0) 87 | 88 | //: Array.reduce 89 | /*: 90 | A series of functions that use the Array.reduce method 91 | 92 | anArray.reduce(initialValue) { (finalValue, elementValue) in PERFORM_CALCULATION } 93 | 94 | 1. finalValue is assigned initialValue 95 | 2. Calculation is performed 96 | 3. finalValue is returned for assignment 97 | */ 98 | //: Sum values in an Array 99 | let smallArray = Array(1...3) 100 | let arraySum = smallArray.reduce(0) { (total, i) in total + i } 101 | arraySum 102 | 103 | 104 | let average = arraySum / smallArray.count 105 | 106 | //: Maximum Value in an Array 107 | let maxNum = smallArray.reduce(0) { (total, i) in max(total, i) } // Decrease initial value 0 if max is less than that 108 | maxNum 109 | 110 | 111 | //: Minimum Value in an Array 112 | let minNum = smallArray.reduce(100) { (total, i) in min(total, i) } // Increase initial value 100 if min is greater than that 113 | minNum 114 | 115 | //: Product 116 | 117 | let tmpArray0 = Array(1...5) 118 | let product = tmpArray0.reduce(1) { (total, i) in total * i } 119 | product 120 | 121 | //: Summation and Product without closure 122 | 123 | let tmpSummation = Array(1...100).reduce(0, +) 124 | let tmpProduct = Array(1...10).reduce(1, *) 125 | 126 | //: Reverse Array with reduce() 127 | 128 | let reverseIntArray = Array(1...10).reduce([Int](), { [$1] + $0 }) 129 | reverseIntArray 130 | 131 | let reverseStringArray = ["dog","cat", "bird", "rabbit"].reduce([String](), { [$1] + $0 }) 132 | reverseStringArray 133 | 134 | //: [Next](@next) 135 | -------------------------------------------------------------------------------- /array.md: -------------------------------------------------------------------------------- 1 | [Basics](README.md) | [Arrays](array.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 2 | 3 | ## Swift Arrays/Lists 4 | 5 | 6 | ### Array Creation 7 | 8 | ```swift 9 | var anArray = ["one", "two", "three","one"] // Mutable 10 | 11 | let anImmutableArray = ["four", "five"] // Immutable 12 | 13 | let numbers = Array(1...10) // 1 through 10 14 | 15 | let numbers9 = Array(1..<10) // 1 through 9 16 | 17 | let numbers0_9 = [Int](0..<10) 18 | let tens:[Int] = (10...100).filter{$0 % 10 == 0} // 10,20,...,100 19 | 20 | var zeroArray = Array(repeating: 0, count: 100) 21 | var strArray = Array(repeating: "", count: 100) 22 | //let total = numbers0_9.reduce(0, +) 23 | 24 | ``` 25 | 26 | 27 | ### Multidimensional Array 28 | ```swift 29 | let multDim:[[Int]] = [[1,2,3], [4,5,6], [7,8,9]] 30 | ``` 31 | 32 | ### Add Value 33 | 34 | ```swift 35 | let arr2 = anArray + ["Swift"] // merge the two arrays 36 | anArray.append("x") // Add value to the end, mutating array 37 | ``` 38 | 39 | ### First element of array 40 | 41 | ```swift 42 | anArray.first // a Swift solution. nil if empty 43 | 44 | anArray[0] // Classic solution. Error if empty 45 | ``` 46 | 47 | 48 | ### Last element of array 49 | 50 | ```swift 51 | anArray.last // a Swift solution. nil if empty 52 | 53 | anArray[anArray.count-1] // Classic solution. Error if empty 54 | ``` 55 | 56 | 57 | ### Empty Array 58 | 59 | ```swift 60 | var emptyArray:[String] = [] 61 | 62 | if emptyArray.isEmpty { 63 | 64 | print("Empty Array") 65 | 66 | } 67 | 68 | 69 | emptyArray.first // Returns nil 70 | 71 | emptyArray.last // Returns nil 72 | ``` 73 | 74 | 75 | 76 | ### Does value exist in array? 77 | 78 | ```swift 79 | if anArray.contains("three") { 80 | 81 | print("Array contains value") 82 | 83 | } 84 | ``` 85 | 86 | 87 | ### removeAll(where predicate: {}) 88 | 89 | Remove all matching elements in O(n) time. 90 | 91 | 92 | ### How to filter array to get unique items? 93 | 94 | Create a Set then build array from it. Set guarantees uniqueness 95 | ```swift 96 | var aSet:Set = [] 97 | 98 | anArray.forEach{aSet.insert($0)} // Could do this: aSet = Set(anArray) 99 | 100 | aSet.count 101 | 102 | anArray = Array(aSet) 103 | 104 | anArray.count 105 | ``` 106 | 107 | 108 | 109 | ### Merge arrays 110 | 111 | ```swift 112 | // Just like prior solution. Uses Set's union function 113 | 114 | // Also skip closure 115 | 116 | 117 | 118 | anArray = ["one", "two", "three","one"] 119 | 120 | aSet = Set(anArray) 121 | 122 | aSet.formUnion(anImmutableArray) 123 | 124 | aSet.count 125 | 126 | anArray = Array(aSet) 127 | 128 | anArray.count 129 | ``` 130 | 131 | 132 | 133 | ### Sort Array 134 | 135 | ```swift 136 | anArray = ["one", "two", "three","one"] 137 | 138 | let sortedArray = anArray.sorted() // Returns a new sorted array 139 | 140 | let sortedArrayReverse = anArray.sorted(by: >) // Reverse order 141 | 142 | 143 | 144 | sortedArray 145 | 146 | sortedArrayReverse 147 | 148 | anArray 149 | 150 | 151 | anArray.sort() // Update the array in place 152 | 153 | anArray 154 | 155 | anArray.removeLast() 156 | 157 | anArray.removeFirst() 158 | ``` 159 | 160 | 161 | 162 | ### Find the index of an element in an Array 163 | ```swift 164 | anArray = ["one", "two", "three","one"] 165 | 166 | anArray.index(of: "two") 167 | ``` 168 | 169 | 170 | 171 | 172 | ### indexOf() can also be used to search an array 173 | 174 | ```swift 175 | let aNumericArray = [1, 2, 10, 20, 100] 176 | 177 | let x = aNumericArray.index(where: {$0 > 10}) // Find the index of first value greater than 10 178 | 179 | print(x ?? 0) 180 | ``` 181 | 182 | 183 | 184 | ### Array.reduce 185 | 186 | 187 | A series of functions that use the Array.reduce method 188 | 189 | anArray.reduce(initialValue) { (finalValue, elementValue) in PERFORM_CALCULATION } 190 | 191 | 192 | 1. finalValue is assigned initialValue 193 | 194 | 2. Calculation is performed 195 | 196 | 3. finalValue is returned for assignment 197 | 198 | 199 | 200 | ### Sum values in an Array 201 | 202 | ```swift 203 | let smallArray = Array(1...3) 204 | 205 | let arraySum = smallArray.reduce(0) { (total, i) in total + i } 206 | 207 | arraySum 208 | ``` 209 | 210 | 211 | 212 | ### Average value of array items 213 | 214 | ```swift 215 | 216 | let average = arraySum / smallArray.count 217 | ``` 218 | 219 | 220 | 221 | 222 | ### Maximum Value in an Array 223 | 224 | ```swift 225 | let maxNum = smallArray.reduce(0) { (total, i) in max(total, i) } // Decrease initial value 0 if max is less than that 226 | 227 | maxNum 228 | ``` 229 | 230 | 231 | 232 | 233 | ### Minimum Value in an Array 234 | 235 | ```swift 236 | let minNum = smallArray.reduce(100) { (total, i) in min(total, i) } // Increase initial value 100 if min is greater than that 237 | 238 | minNum 239 | ``` 240 | 241 | 242 | 243 | ### Product 244 | 245 | ```swift 246 | 247 | let tmpArray0 = Array(1...5) 248 | 249 | let product = tmpArray0.reduce(1) { (total, i) in total * i } 250 | 251 | product 252 | 253 | ``` 254 | 255 | 256 | ### Summation and Product without closure 257 | 258 | 259 | ```swift 260 | let tmpSummation = Array(1...100).reduce(0, +) 261 | 262 | let tmpProduct = Array(1...10).reduce(1, *) 263 | ``` 264 | 265 | 266 | ### Reverse Array with reduce() 267 | 268 | 269 | ```swift 270 | let reverseIntArray = Array(1...10).reduce([Int](), { [$1] + $0 }) 271 | 272 | 273 | 274 | let reverseStringArray = ["dog","cat", "bird", "rabbit"].reduce([String](), { [$1] + $0 }) 275 | 276 | reverseStringArray 277 | ``` 278 | 279 | -------------------------------------------------------------------------------- /strings.md: -------------------------------------------------------------------------------- 1 | [Basics](README.md) | [Arrays](array.md) | [Colors](color.md) | [Date and Time](Dates/README.md) | [Dictionaries](dictionary.md) | [Sets](sets.md) | [Sorting](sorting.md) | [Strings](strings.md) | [Functional Swift](functional.md) 2 | 3 | ## Swift Strings 4 | 5 | 6 | ### String Creation 7 | 8 | ```swift 9 | var mystr:String // Mutable string 10 | 11 | mystr = "\n" // a newline character 12 | let s1 = "\\n" // Two characters, \ and n 13 | let bear = "🐻" 14 | 15 | mystr = "Jon \"Maddog\" Orwant" // escaped double quote 16 | var str = "Hello, playground" // Mutable string 17 | let language = "Swift" // Immutable string 18 | 19 | 20 | var str1: String 21 | var str2: String = "hello world" 22 | ``` 23 | 24 | ### String Length 25 | 26 | ```swift 27 | let stringLength = str.count 28 | ``` 29 | 30 | ### String Equality 31 | 32 | ```swift 33 | if str == "Hello, playground" { 34 | print("Strings are Equal") 35 | } 36 | ``` 37 | 38 | ### Case Insensitive Comparison 39 | 40 | ```swift 41 | let nativeLanguage = "French" 42 | if nativeLanguage.caseInsensitiveCompare("french") == .orderedSame { // NSComparisonResult.OrderedSame 43 | print("Strings are equal") 44 | } 45 | ``` 46 | 47 | ### String Inequality 48 | 49 | ```swift 50 | if str != "Hello world" { 51 | print("Strings are NOT Equal") 52 | } 53 | ``` 54 | 55 | 56 | ### Test for Empty String 57 | ```swift 58 | var aString = "" 59 | if aString.isEmpty { 60 | print("String is empty") 61 | } 62 | ``` 63 | 64 | 65 | ### Concatenate 66 | 67 | ```swift 68 | str1 = "Hello, " 69 | str2 = "playground" 70 | 71 | str = str1 + str2 // Swift's concatenate operation 72 | str = "\(str1)\(str2)" // Using String interpolation 73 | ``` 74 | 75 | ### Append string 76 | 77 | ```swift 78 | str = "hello" 79 | str += " world" 80 | ``` 81 | 82 | ### Append a single character 83 | 84 | ```swift 85 | let period: Character = "." 86 | str.append(period) 87 | ``` 88 | 89 | 90 | ### Prepend string 91 | 92 | ```swift 93 | _ = "My \(str)" // Ignoring result 94 | _ = "My " + str 95 | ``` 96 | 97 | ### Remove Last Character/chop 98 | 99 | ```swift 100 | var s = "abcd" 101 | let lastChar: Character = s.removeLast() // mutates s == "abc" 102 | ``` 103 | 104 | ### Simple CSV split 105 | 106 | ```swift 107 | let csv = "one,two,3" 108 | 109 | let anArray = csv.components(separatedBy: ",") 110 | print(anArray) 111 | ``` 112 | 113 | ### Join string to CSV 114 | 115 | ```swift 116 | anArray.joined(separator: ",") 117 | //: String Contains a Substring 118 | 119 | str = "www" 120 | let url = "https://www.h4labs.com/" 121 | 122 | if url.contains(str) { 123 | print("Contains string: \(str)") 124 | } 125 | ``` 126 | 127 | ### Replace/Remove All Characters in String 128 | 129 | ```swift 130 | let row = "id first last" 131 | let csv = row.replacingOccurrences(of: " ", with: ",") // import Foundation 132 | let noSpaces = row.replacingOccurrences(of: " ", with: "") 133 | 134 | var s = "## header" 135 | s.removeAll(where: ["<", ">"].contains) // mutate s - Set 136 | 137 | ``` 138 | 139 | ### String begins with/Has prefix 140 | 141 | ```swift 142 | url.hasPrefix("https:") 143 | ``` 144 | 145 | ### String ends with/Has suffix 146 | 147 | ```swift 148 | url.hasSuffix("/") 149 | ``` 150 | 151 | 152 | ### String to Letter Array/Split string by character 153 | 154 | ```swift 155 | var letters:[String] = [] 156 | "horse".forEach {letters.append(String($0))} 157 | letters 158 | ``` 159 | 160 | ```swift 161 | let arr = str.map { String($0) } 162 | ``` 163 | 164 | ### Trim White Space 165 | 166 | ```swift 167 | var blogTitle = " Swift Cookbook ".trimmingCharacters(in: NSCharacterSet.whitespaces) 168 | 169 | //stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) 170 | ``` 171 | 172 | 173 | ### Trim White Space and Remove Newlines 174 | 175 | ```swift 176 | blogTitle = " Swift Cookbook \n".trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) 177 | //: Remove surrounding quotes 178 | let quotedString = "\"h4labs\"" 179 | 180 | let quotesRemoved = quotedString.replacingOccurrences(of: "\"", with: "") 181 | ``` 182 | 183 | 184 | ### Uppercase string 185 | 186 | ```swift 187 | var company = "apple computer" 188 | company = company.uppercased() 189 | ``` 190 | 191 | ### Capitalize/Title case 192 | 193 | ```swift 194 | company = company.capitalized// capitalize every word 195 | company = company.localizedCapitalized // capitalize every word localized 196 | ``` 197 | 198 | ### Lowercase 199 | 200 | ```swift 201 | company = company.lowercased() 202 | ``` 203 | 204 | ### Loop Over Every Character of String 205 | 206 | ```swift 207 | for character in "hello world" { 208 | print(character) 209 | } 210 | ``` 211 | 212 | ```swift 213 | let letters = "abcdefg" 214 | var csv = "" 215 | for character in letters { 216 | csv.append(character) 217 | csv.append(",") 218 | } 219 | print(csv) 220 | ``` 221 | 222 | ### String to Int 223 | 224 | ```swift 225 | let aNumberStr = "10" 226 | let anInt: Int? = Int(aNumberStr) 227 | let i: Int = Int(aNumberStr) ?? 0 // default to zero and make nonnullable 228 | ``` 229 | 230 | ### String to Double 231 | 232 | ```swift 233 | let aDouble: Double? = Double(aNumberStr) 234 | ``` 235 | 236 | ### First letter 237 | 238 | ```swift 239 | let aWord = "hello" 240 | let firstLetter = aWord.first 241 | let lastLetter = aWord.last 242 | let x = aWord.prefix(3) 243 | String(x) 244 | ``` 245 | 246 | ### Multi-line Strings 247 | 248 | ```swift 249 | let str = """ 250 | .#..# 251 | ..... 252 | ##### 253 | ....# 254 | ...## 255 | """ 256 | ``` 257 | 258 | 259 | ## TODO 260 | 261 | ### Is a String a Digit/isDigit 262 | 263 | ```swift 264 | 265 | ``` 266 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /SwiftCookBook.playground/Pages/Date_Time.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: 2 | Swift Cookbook Date/Time Functions 3 | Copy and Paste into a Swift Playground 4 | Version: 20151020.01 5 | - [h4labs Swift Cookbook](http://www.h4labs.com/dev/ios/swift_cookbook.html) 6 | 7 | Some ideas came from [Perl](http://pleac.sourceforge.net/pleac_perl/arrays.html) and [Python](http://pleac.sourceforge.net/pleac_python/datesandtimes.html) Pleacs. 8 | */ 9 | 10 | import Foundation 11 | 12 | //: Current Date/Time 13 | 14 | var aDate: Date 15 | let now = Date() // Current Date/Time 16 | 17 | 18 | //: Date from String 19 | let microsoftDateStr = "1986-03-13" // year-month-day 20 | 21 | // Set date format 22 | var dateFmt = DateFormatter() 23 | dateFmt.timeZone = NSTimeZone.default 24 | dateFmt.dateFormat = "yyyy-MM-dd" 25 | microsoftDateStr 26 | 27 | 28 | // Get Date for the given string 29 | dateFmt.date(from: microsoftDateStr) 30 | var microsoftIpoDate = dateFmt.date(from: microsoftDateStr) 31 | 32 | print(microsoftIpoDate!) 33 | microsoftIpoDate 34 | 35 | //: Date Using Date Components 36 | var components = DateComponents() 37 | components.year = 1980 38 | components.month = 12 39 | components.day = 12 40 | 41 | 42 | // Get Date given the above date components 43 | var appleIpoDate = Calendar(identifier: .gregorian).date(from: components) 44 | 45 | print(appleIpoDate!) 46 | 47 | let ipoDates = [appleIpoDate, microsoftIpoDate] 48 | ipoDates.first 49 | 50 | 51 | func iPhoneBirthday() -> Date { 52 | 53 | var components = DateComponents() 54 | components.year = 2007 55 | components.month = 1 56 | components.day = 9 57 | components.hour = 9 58 | components.minute = 41 59 | components.second = 0 60 | 61 | let aDate = Calendar(identifier: .gregorian).date(from: components) 62 | 63 | return aDate! 64 | } 65 | 66 | let bDay = iPhoneBirthday() 67 | 68 | //: Standard Date Formats 69 | /*: 70 | # Standard Formats 71 | 72 | Short | Short | 1/9/07, 9:41 AM 73 | 74 | Short | Medium | 1/9/07, 9:41:00 AM 75 | 76 | Short | Long | 1/9/07, 9:41:00 AM EST 77 | 78 | Short | Full | 1/9/07, 9:41:00 AM Eastern Standard Time 79 | 80 | Medium | Short | Jan 9, 2007, 9:41 AM 81 | 82 | Medium | Medium | Jan 9, 2007, 9:41:00 AM 83 | 84 | Medium | Long | Jan 9, 2007, 9:41:00 AM EST 85 | 86 | Medium | Full | Jan 9, 2007, 9:41:00 AM Eastern Standard Time 87 | 88 | Long | Short | January 9, 2007 at 9:41 AM 89 | 90 | Long | Medium | January 9, 2007 at 9:41:00 AM 91 | 92 | Long | Long | January 9, 2007 at 9:41:00 AM EST 93 | 94 | Long | Full | January 9, 2007 at 9:41:00 AM Eastern Standard Time 95 | 96 | Full | Short | Tuesday, January 9, 2007 at 9:41 AM 97 | 98 | Full | Medium | Tuesday, January 9, 2007 at 9:41:00 AM 99 | 100 | Full | Long | Tuesday, January 9, 2007 at 9:41:00 AM EST 101 | 102 | Full | Full | Tuesday, January 9, 2007 at 9:41:00 AM Eastern Standard Time 103 | 104 | 105 | 106 | */ 107 | func formatDates(aDate:Date) { 108 | 109 | let dateStyles:[DateFormatter.Style] = [.short, .medium, .long, .full] 110 | 111 | let styleNames = ["", "Short", "Medium", "Long", "Full"] 112 | let formatter = DateFormatter() 113 | for style in dateStyles { 114 | for style2 in dateStyles { 115 | formatter.dateStyle = style 116 | formatter.timeStyle = style2 117 | 118 | let dateString = formatter.string(from: aDate) 119 | let styleNames0 = "\(styleNames[Int(style.rawValue)]) | \(styleNames[Int(style2.rawValue)])" 120 | print("\(styleNames0) | \(dateString)") 121 | } 122 | } 123 | } 124 | 125 | formatDates(aDate: bDay) 126 | 127 | // Get Date for the given string 128 | dateFmt.date(from: microsoftDateStr) 129 | 130 | //: Current Year 131 | 132 | func year() -> Int { 133 | 134 | let date = Date() 135 | let calendar = Calendar.current 136 | let components = calendar.dateComponents([.year], from: date) 137 | 138 | let year = components.year 139 | 140 | return year! 141 | } 142 | 143 | //: Year/Month/Day returned as a tuple 144 | 145 | func yearMonthDay(date:Date) -> (Int, Int, Int) { 146 | 147 | let calendar = Calendar.current 148 | let components = calendar.dateComponents([.year, .month, .day], from: date) 149 | 150 | let year = components.year 151 | let month = components.month 152 | let day = components.day 153 | 154 | return (year!, month!, day!) 155 | } 156 | 157 | 158 | let (y,m,d) = yearMonthDay(date: Date()) 159 | 160 | //: Add leading zeros for month/day 161 | print("The date is %d-%d-%d", y,m,d) 162 | 163 | //: Day of Year 164 | func dayOfYear() -> Int { 165 | let date = Date() // now 166 | let calendar = Calendar.current 167 | 168 | let day = calendar.ordinality(of: .day, in: .year, for: date) 169 | 170 | return day! 171 | } 172 | 173 | year() 174 | 175 | dayOfYear() 176 | 177 | 178 | //: Tomorrow 179 | func tomorrow() -> Date { 180 | 181 | var dateComponents = DateComponents() 182 | 183 | dateComponents.setValue(1, for: .day); 184 | 185 | let now = Date() 186 | let tomorrow = Calendar.current.date(byAdding: dateComponents, to: now) 187 | 188 | return tomorrow! 189 | } 190 | 191 | tomorrow() 192 | 193 | //: Yesterday 194 | func yesterday() -> Date { 195 | 196 | var dateComponents = DateComponents() 197 | dateComponents.setValue(-1, for: .day) // -1 days 198 | 199 | let now = Date() 200 | let yesterday = Calendar.current.date(byAdding: dateComponents, to: now) 201 | return yesterday! 202 | } 203 | yesterday() 204 | 205 | 206 | //: Day of Week 207 | 208 | func dayOfWeek() -> Int { 209 | let weekday:Int 210 | 211 | let now = Date() 212 | 213 | let gregorian = Calendar(identifier: .gregorian) 214 | 215 | let x = gregorian.dateComponents([.weekdayOrdinal], from: now) 216 | gregorian.firstWeekday 217 | 218 | weekday = x.weekdayOrdinal! 219 | 220 | return weekday 221 | } 222 | 223 | dayOfWeek() 224 | 225 | //: Last day of month 226 | 227 | func lastDayOfMonth(_ aDate:Date) -> Date { 228 | 229 | let calendar = Calendar(identifier: .gregorian) 230 | var components = calendar.dateComponents([.year , .month , .day], 231 | from:aDate) 232 | // components.month += 1 // Next month 233 | 234 | components.day = 0 // Set the day to zero to get last day of prior month 235 | 236 | let aDate = calendar.date(from: components) 237 | 238 | return aDate! 239 | } 240 | 241 | lastDayOfMonth(now) 242 | 243 | func lastDaysOfMonthForYear(year:Int) -> [Date] { 244 | 245 | var result:[Date] = [] 246 | 247 | var components = DateComponents() 248 | components.year = year 249 | components.day = 1 250 | 251 | for month in 1...12 { 252 | components.month = month 253 | 254 | let aDate = Calendar(identifier: .gregorian).date(from: components) 255 | 256 | let d = lastDayOfMonth(aDate!) 257 | result += [d] 258 | } 259 | return result 260 | } 261 | 262 | lastDaysOfMonthForYear(year: 2016) 263 | //: Add n days - Can be positive or negative 264 | func addDays(_ numDays:Int) -> Date { 265 | 266 | var dateComponents = DateComponents() 267 | dateComponents.setValue(numDays, for: .day) // -1 days 268 | 269 | let now = Date() 270 | let newDay = Calendar.current.date(byAdding: dateComponents, to: now) 271 | // let newDay = Calendar.current.date(dateComponents, to: now, options: NSCalendar.Options(rawValue: 0)) 272 | return newDay! 273 | } 274 | 275 | addDays(1) 276 | addDays(-1) 277 | 278 | 279 | //: Last Saturday 280 | 281 | //: Date Difference: Number of days between two dates 282 | func dateDiff(startDate:Date, endDate:Date) -> Int { 283 | let calendar = Calendar.current 284 | 285 | // Ignore hours/minutes/seconds 286 | let date1 = calendar.startOfDay(for: startDate) 287 | let date2 = calendar.startOfDay(for: endDate) 288 | // let unit = [Calendar.Component.day] 289 | 290 | let components = calendar.dateComponents([.day], from: date1, to: date2) 291 | 292 | return abs(components.day!) 293 | } 294 | 295 | dateDiff(startDate: lastDayOfMonth(now), endDate: now) 296 | 297 | //: Leap Year 298 | func isLeapYear(_ year: Int) -> Bool { 299 | 300 | let isLeapYear = ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)) 301 | 302 | 303 | return isLeapYear 304 | } 305 | 306 | func isLeapYear(date: Date = Date()) -> Bool { 307 | 308 | let calendar = Calendar.current 309 | let components = calendar.dateComponents([.year], from: date) 310 | 311 | let year = components.year 312 | return isLeapYear(year!) 313 | } 314 | 315 | isLeapYear(1900) // false 316 | isLeapYear(2000) // true 317 | isLeapYear(2015) // false 318 | isLeapYear(2016) // true 319 | 320 | //let now0 = Date() 321 | //isLeapYear(now0) 322 | 323 | isLeapYear() // Default parameter is Date() 324 | 325 | 326 | //: Date from Int YYYYMMDD 327 | func dateFromInt(_ date:Int) -> Date { 328 | 329 | let year = date / 10000 330 | let month = date % 10000 / 100 331 | let day = date % 100 332 | 333 | var components = DateComponents() 334 | components.year = year 335 | components.month = month 336 | components.day = day 337 | 338 | let aDate = Calendar(identifier: .gregorian).date(from: components) 339 | 340 | return aDate! 341 | } 342 | 343 | let d0 = dateFromInt(20160111) 344 | 345 | //: Date to Int YYYYMMDD 346 | func intFromDate(_ date:Date) -> Int { 347 | 348 | let calendar = Calendar.current 349 | let components = calendar.dateComponents([.year, .month, .day], from: date) 350 | 351 | let year = components.year 352 | let month = components.month 353 | let day = components.day 354 | 355 | let intDate = year! * 10000 + month! * 100 + day! 356 | return intDate 357 | 358 | } 359 | 360 | let d1 = intFromDate(Date()) 361 | 362 | //: Parsing Date Strings 363 | 364 | //: Formatted Date Strings 365 | --------------------------------------------------------------------------------