├── 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 |
--------------------------------------------------------------------------------