└── Swifter.playground
├── Pages
├── assert.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── associated-object.xcplaygroundpage
│ └── Contents.swift
├── associatedtype.xcplaygroundpage
│ └── Contents.swift
├── autoclosure.xcplaygroundpage
│ └── Contents.swift
├── class-cluster.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── closure-ambiguous.xcplaygroundpage
│ └── Contents.swift
├── currying.xcplaygroundpage
│ └── Contents.swift
├── default-param.xcplaygroundpage
│ └── Contents.swift
├── delegate.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── documentation.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── enum-enumerate.xcplaygroundpage
│ └── Contents.swift
├── enumerate.xcplaygroundpage
│ └── Contents.swift
├── equal.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── error-handle.xcplaygroundpage
│ └── Contents.swift
├── escaping.xcplaygroundpage
│ └── Contents.swift
├── extension-generic.xcplaygroundpage
│ └── Contents.swift
├── fatalError.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── final.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── func-dispatch.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── func-params.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── gcd-delay.xcplaygroundpage
│ └── Contents.swift
├── general.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── hash.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── indirect-nested-enum.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── init-keyword.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── init-nil.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── init.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── instance-type.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── intropection.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── json.xcplaygroundpage
│ ├── Contents.swift
│ └── Sources
│ │ └── SwiftyJSON.swift
├── kvo.xcplaygroundpage
│ ├── Contents.swift
│ └── Sources
│ │ └── delay.swift
├── lazy.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── literal.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── local-scope.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── lock.xcplaygroundpage
│ └── Contents.swift
├── log.xcplaygroundpage
│ └── Contents.swift
├── math-number.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── memory-retain-cycle.xcplaygroundpage
│ └── Contents.swift
├── multi-collection.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── multi-method.xcplaygroundpage
│ └── Contents.swift
├── multiple-optional.xcplaygroundpage
│ └── Contents.swift
├── nsnull.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── objc-dynamic.xcplaygroundpage
│ └── Contents.swift
├── objc-protocol.xcplaygroundpage
│ └── Contents.swift
├── operator.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── optional-chaining.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── optional-map.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── options.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── output-format.xcplaygroundpage
│ └── Contents.swift
├── overflow.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── pattern-match.xcplaygroundpage
│ └── Contents.swift
├── playground-delay.xcplaygroundpage
│ └── Contents.swift
├── playground-liveview.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── pointer-memory.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── print.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── property-observer.xcplaygroundpage
│ └── Contents.swift
├── protocol-extension.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── protocol-mutating.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── random-number.xcplaygroundpage
│ └── Contents.swift
├── range.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── reflect.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── regex.xcplaygroundpage
│ └── Contents.swift
├── selector.xcplaygroundpage
│ └── Contents.swift
├── self-anyclass.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── sequence.xcplaygroundpage
│ └── Contents.swift
├── singleton.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── static-class.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── string-nsstring.xcplaygroundpage
│ └── Contents.swift
├── struct-mutating.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── subscript.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── tail-recursion.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── toll-free.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── tuple.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── type-encode.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── typealias.xcplaygroundpage
│ └── Contents.swift
├── unsafe.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── use-self.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── value-reference.xcplaygroundpage
│ └── Contents.swift
├── variadic.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
└── where.xcplaygroundpage
│ ├── Contents.swift
│ └── timeline.xctimeline
├── contents.xcplayground
└── playground.xcworkspace
├── contents.xcworkspacedata
├── xcshareddata
└── Swifter.xcscmblueprint
└── xcuserdata
├── JP20028.xcuserdatad
├── UserInterfaceState.xcuserstate
└── userinterfacestate (Wei Wang の競合コピー 2016-09-07).xcuserstate
└── onevcat.xcuserdatad
├── UserInterfaceState (Wei Wang の競合コピー 2016-09-07).xcuserstate
└── UserInterfaceState.xcuserstate
/Swifter.playground/Pages/assert.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let absoluteZeroInCelsius = -273.15
5 |
6 | func convertToKelvin(_ celsius: Double) -> Double {
7 | assert(celsius > absoluteZeroInCelsius, "输入的摄氏温度不能低于绝对零度")
8 | return celsius - absoluteZeroInCelsius
9 | }
10 |
11 | let roomTemperature = convertToKelvin(27)
12 | // roomTemperature = 300.15
13 |
14 | let tooCold = convertToKelvin(-300)
15 | // 运行时错误:
16 | // assertion failed:
17 | // 输入的摄氏温度不能低于绝对零度 : file {YOUR_FILE_PATH}, line {LINE_NUMBER}
18 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/assert.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/associated-object.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | // MyClass.swift
5 | class MyClass {
6 | }
7 |
8 | // MyClassExtension.swift
9 | private var key: Void?
10 |
11 | extension MyClass {
12 | var title: String? {
13 | get {
14 | return objc_getAssociatedObject(self, &key) as? String
15 | }
16 |
17 | set {
18 | objc_setAssociatedObject(self,
19 | &key, newValue,
20 | .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
21 | }
22 | }
23 | }
24 |
25 |
26 | // 测试
27 | func printTitle(_ input: MyClass) {
28 | if let title = input.title {
29 | print("Title: \(title)")
30 | } else {
31 | print("没有设置")
32 | }
33 | }
34 |
35 | let a = MyClass()
36 | printTitle(a)
37 | a.title = "Swifter.tips"
38 | printTitle(a)
39 |
40 | // 输出:
41 | // 没有设置
42 | // Title: Swifter.tips
43 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/associatedtype.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | protocol Food { }
5 |
6 | protocol Animal {
7 | associatedtype F: Food
8 | func eat(_ food: F)
9 | }
10 |
11 | struct Meat: Food { }
12 | struct Grass: Food { }
13 |
14 | struct Tiger: Animal {
15 | func eat(_ food: Meat) {
16 | print("eat \(food)")
17 | }
18 | }
19 |
20 | let meat = Meat()
21 | Tiger().eat(meat)
22 |
23 | struct Sheep: Animal {
24 | func eat(_ food: Grass) {
25 | print("eat \(food)")
26 | }
27 | }
28 |
29 | //func isDangerous(animal: Animal) -> Bool {
30 | // return false
31 | //}
32 |
33 | func isDangerous(animal: T) -> Bool {
34 | if animal is Tiger {
35 | return true
36 | } else {
37 | return false
38 | }
39 | }
40 |
41 | isDangerous(animal: Tiger())
42 | isDangerous(animal: Sheep())
--------------------------------------------------------------------------------
/Swifter.playground/Pages/autoclosure.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func logIfTrue(_ predicate: () -> Bool) {
5 | if predicate() {
6 | print("True")
7 | }
8 | }
9 |
10 | logIfTrue({return 2 > 1})
11 | logIfTrue({2 > 1})
12 | logIfTrue{2 > 1}
13 |
14 |
15 | func logIfTrue(_ predicate: @autoclosure () -> Bool) {
16 | if predicate() {
17 | print("True")
18 | }
19 | }
20 |
21 | logIfTrue(2 > 1)
22 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/class-cluster.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | class Drinking {
5 | typealias LiquidColor = UIColor
6 | var color: LiquidColor {
7 | return .clear
8 | }
9 |
10 | class func drinking(name: String) -> Drinking {
11 | var drinking: Drinking
12 | switch name {
13 | case "Coke":
14 | drinking = Coke()
15 | case "Beer":
16 | drinking = Beer()
17 | default:
18 | drinking = Drinking()
19 | }
20 |
21 | return drinking
22 | }
23 | }
24 |
25 | class Coke: Drinking {
26 | override var color: LiquidColor {
27 | return .black
28 | }
29 | }
30 |
31 | class Beer: Drinking {
32 | override var color: LiquidColor {
33 | return .yellow
34 | }
35 | }
36 |
37 | let coke = Drinking.drinking(name: "Coke")
38 | coke.color // Black
39 |
40 | let beer = Drinking.drinking(name: "Beer")
41 | beer.color // Yellow
42 |
43 |
44 | let cokeClass = NSStringFromClass(type(of: coke)) //Coke
45 |
46 | let beerClass = NSStringFromClass(type(of: beer)) //Beer
47 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/class-cluster.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/closure-ambiguous.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | extension Int {
5 | func times(f: (Int) -> ()) {
6 | print("Int")
7 | for i in 1...self {
8 | f(i)
9 | }
10 | }
11 | }
12 |
13 | 3.times { (i: Int) -> () in
14 | print(i)
15 | }
16 | // 输出:
17 | // Int
18 | // 1
19 | // 2
20 | // 3
21 |
22 | 3.times { i in
23 | print(i)
24 | }
25 | // 输出:
26 | // Int
27 | // 1
28 | // 2
29 | // 3
30 |
31 |
32 | //extension Int {
33 | // func times(f: Void -> Void) {
34 | // print("Void")
35 | // for i in 1...self {
36 | // f()
37 | // }
38 | // }
39 | //}
40 | // Swift 1.2 之前:
41 | // 输出:
42 | // Void
43 | //
44 | //
45 | //
46 | // Swift 1.2 之后由于歧义,无法编译
47 |
48 | //extension Int {
49 | // func times(f: (Int, Int) -> ()) {
50 | // print("Tuple")
51 | // for i in 1...self {
52 | // f(i, i)
53 | // }
54 | // }
55 | //}
56 | // 注释掉开头的 times(f: Int -> ())
57 | // 3.times { i in
58 | // print(i)
59 | // }
60 | // 输出为
61 | // Tuple
62 | // (1, 1)
63 | // (2, 2)
64 | // (3, 3)
65 |
66 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/currying.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func addOne(num: Int) -> Int {
5 | return num + 1
6 | }
7 |
8 | func addTo(_ adder: Int) -> (Int) -> Int {
9 | return {
10 | num in
11 | return num + adder
12 | }
13 | }
14 |
15 | let addTwo = addTo(2) // addToFour: Int -> Int
16 | let result = addTwo(6) // result = 8
17 |
18 | func greaterThan(_ comparer: Int) -> (Int) -> Bool {
19 | return { $0 > comparer }
20 | }
21 |
22 | let greaterThan10 = greaterThan(10);
23 |
24 | greaterThan10(13) // => true
25 | greaterThan10(9) // => false
26 |
27 | protocol TargetAction {
28 | func performAction()
29 | }
30 |
31 | struct TargetActionWrapper: TargetAction {
32 | weak var target: T?
33 | let action: (T) -> () -> ()
34 |
35 | func performAction() -> () {
36 | if let t = target {
37 | action(t)()
38 | }
39 | }
40 | }
41 |
42 | enum ControlEvent {
43 | case TouchUpInside
44 | case ValueChanged
45 | // ...
46 | }
47 |
48 |
49 | class Control {
50 | var actions = [ControlEvent: TargetAction]()
51 |
52 | func setTarget(target: T,
53 | action: @escaping (T) -> () -> (), controlEvent: ControlEvent) {
54 |
55 | actions[controlEvent] = TargetActionWrapper(
56 | target: target, action: action)
57 | }
58 |
59 | func removeTargetForControlEvent(controlEvent: ControlEvent) {
60 | actions[controlEvent] = nil
61 | }
62 |
63 | func performActionForControlEvent(controlEvent: ControlEvent) {
64 | actions[controlEvent]?.performAction()
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/default-param.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func sayHello1(str1: String = "Hello", str2: String, str3: String) {
5 | print(str1 + str2 + str3)
6 | }
7 |
8 | func sayHello2(str1: String, str2: String, str3: String = "World") {
9 | print(str1 + str2 + str3)
10 | }
11 |
12 | sayHello1(str2: " ", str3: "World")
13 | sayHello2(str1: "Hello", str2: " ")
14 |
15 | //输出都是 Hello World
16 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/delegate.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | protocol MyClassDelegate: class {
5 | func method()
6 | }
7 |
8 | class MyClass {
9 | weak var delegate: MyClassDelegate?
10 | }
11 |
12 | class ViewController: UIViewController, MyClassDelegate {
13 | // ...
14 | var someInstance: MyClass!
15 |
16 | override func viewDidLoad() {
17 | super.viewDidLoad()
18 |
19 | someInstance = MyClass()
20 | someInstance.delegate = self
21 | }
22 |
23 | func method() {
24 | print("Do something")
25 | }
26 |
27 | //...
28 | }
29 |
30 | // weak var delegate: MyClassDelegate? 编译错误
31 | // 'weak' cannot be applied to non-class type 'MyClassDelegate'
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/delegate.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/documentation.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | /**
5 | A demo method
6 |
7 | - parameter input: An Int number
8 |
9 | - returns: The string represents the input number
10 | */
11 | func method(input: Int) -> String {
12 | return String(input)
13 | }
14 |
15 | struct Person {
16 | /// name of the person
17 | var name: String
18 | }
19 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/documentation.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/enum-enumerate.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | enum Suit: String {
5 | case spades = "黑桃"
6 | case hearts = "红桃"
7 | case clubs = "草花"
8 | case diamonds = "方片"
9 | }
10 |
11 | enum Rank: Int, CustomStringConvertible {
12 | case ace = 1
13 | case two, three, four, five, six, seven, eight, nine, ten
14 | case jack, queen, king
15 | var description: String {
16 | switch self {
17 | case .ace:
18 | return "A"
19 | case .jack:
20 | return "J"
21 | case .queen:
22 | return "Q"
23 | case .king:
24 | return "K"
25 | default:
26 | return String(self.rawValue)
27 | }
28 | }
29 | }
30 |
31 | protocol EnumeratableEnum {
32 | static var allValues: [Self] {get}
33 | }
34 |
35 | extension Suit: EnumeratableEnum {
36 | static var allValues: [Suit] {
37 | return [.spades, .hearts, .clubs, .diamonds]
38 | }
39 | }
40 |
41 | extension Rank: EnumeratableEnum {
42 | static var allValues: [Rank] {
43 | return [.ace, .two, .three,
44 | .four, .five, .six,
45 | .seven, .eight, .nine,
46 | .ten, .jack, .queen, .king]
47 | }
48 | }
49 |
50 | for suit in Suit.allValues {
51 | for rank in Rank.allValues {
52 | print("\(suit.rawValue)\(rank)")
53 | }
54 | }
55 |
56 | // 输出:
57 | // 黑桃A
58 | // 黑桃2
59 | // 黑桃3
60 | // ...
61 | // 方片K
62 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/enumerate.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let arr: NSArray = [1,2,3,4,5]
5 | var result = 0
6 |
7 | arr.enumerateObjects ({ (num, idx, stop) -> Void in
8 | result += num as! Int
9 | if idx == 2 {
10 | stop.pointee = true
11 | }
12 | })
13 | print(result)
14 | // 输出:6
15 |
16 | result = 0
17 | for (idx, num) in [1,2,3,4,5].enumerated() {
18 | result += num
19 | if idx == 2 {
20 | break
21 | }
22 | }
23 | print(result)
24 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/equal.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let str1 = "快乐的字符串"
5 | let str2 = "快乐的字符串"
6 | let str3 = "开心的字符串"
7 |
8 | str1 == str2 // true
9 | str1 == str3 // false
10 |
11 | class TodoItem {
12 | let uuid: String
13 | var title: String
14 |
15 | init(uuid: String, title: String) {
16 | self.uuid = uuid
17 | self.title = title
18 | }
19 | }
20 |
21 | extension TodoItem: Equatable {
22 |
23 | }
24 |
25 | func ==(lhs: TodoItem, rhs: TodoItem) -> Bool {
26 | return lhs.uuid == rhs.uuid
27 | }
28 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/equal.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/error-handle.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let d = NSData()
5 |
6 | do {
7 | try d.write(toFile: "Hello", options: [])
8 | } catch let error as NSError {
9 | print ("Error: \(error.domain)")
10 | }
11 |
12 | enum LoginError: Error {
13 | case UserNotFound, UserPasswordNotMatch
14 | }
15 |
16 | func login(user: String, password: String) throws {
17 | let users = [String: String]()
18 |
19 | if !users.keys.contains(user) {
20 | throw LoginError.UserNotFound
21 | }
22 |
23 | if users[user] != password {
24 | throw LoginError.UserPasswordNotMatch
25 | }
26 |
27 | print("Login successfully.")
28 | }
29 |
30 | do {
31 | try login(user: "onevcat", password: "123")
32 | } catch LoginError.UserNotFound {
33 | print("UserNotFound")
34 | } catch LoginError.UserPasswordNotMatch {
35 | print("UserPasswordNotMatch")
36 | }
37 |
38 | // Do something with login user
39 |
40 | enum E: Error {
41 | case Negative
42 | }
43 |
44 | func methodThrowsWhenPassingNegative(number: Int) throws -> Int {
45 | if number < 0 {
46 | throw E.Negative
47 | }
48 | return number
49 | }
50 |
51 | if let num = try? methodThrowsWhenPassingNegative(number: 100) {
52 | print(type(of: num))
53 | } else {
54 | print("failed")
55 | }
56 |
57 | // Never do this!
58 | func methodThrowsWhenPassingNegative1(number: Int) throws -> Int? {
59 | if number < 0 {
60 | throw E.Negative
61 | }
62 | if number == 0 {
63 | return nil
64 | }
65 | return number
66 | }
67 |
68 | if let num = try? methodThrowsWhenPassingNegative1(number: 0) {
69 | print(type(of: num))
70 | } else {
71 | print("failed")
72 | }
73 |
74 | func methodThrows(num: Int) throws {
75 | if num < 0 {
76 | print("Throwing!")
77 | throw E.Negative
78 | }
79 | print("Executed!")
80 | }
81 |
82 | func methodRethrows(num: Int, f: (Int) throws -> ()) rethrows {
83 | try f(num)
84 | }
85 |
86 | do {
87 | try methodRethrows(num: 1, f: methodThrows)
88 | } catch _ {
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/escaping.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import PlaygroundSupport
4 |
5 | PlaygroundPage.current.needsIndefiniteExecution = true
6 |
7 | func doWork(block: ()->()) {
8 | block()
9 | }
10 |
11 | func doWorkAsync(block: @escaping ()->()) {
12 | DispatchQueue.main.async {
13 | block()
14 | }
15 | }
16 |
17 | class S {
18 | var foo = "foo"
19 |
20 | func method1() {
21 | doWork {
22 | print(foo)
23 | }
24 | foo = "bar"
25 | }
26 |
27 | func method2() {
28 | doWorkAsync {
29 | print(self.foo)
30 | }
31 | foo = "bar"
32 | }
33 |
34 | func method3() {
35 | doWorkAsync {
36 | [weak self] _ in
37 | print(self?.foo)
38 | }
39 | foo = "bar"
40 | }
41 | }
42 |
43 | S().method1()
44 | // foo
45 |
46 | S().method2()
47 | // bar
48 |
49 | S().method3()
50 | // nil
51 |
52 | protocol P {
53 | func work(b: @escaping ()->())
54 | }
55 |
56 | class C: P {
57 | func work(b: @escaping () -> ()) {
58 | DispatchQueue.main.async {
59 | print("in C")
60 | b()
61 | }
62 | }
63 | }
64 |
65 | C().work {
66 | print("work!")
67 | }
68 | // in C
69 | // work!
70 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/extension-generic.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | extension Array {
5 | var random: Element? {
6 | return self.count != 0 ?
7 | self[Int(arc4random_uniform(UInt32(self.count)))] :
8 | nil
9 | }
10 |
11 | func appendRandomDescription
12 | (_ input: U) -> String {
13 |
14 | if let element = self.random {
15 | return "\(element) " + input.description
16 | } else {
17 | return "empty array"
18 | }
19 | }
20 | }
21 |
22 | let languages = ["Swift","ObjC","C++","Java"]
23 | languages.random!
24 | // 随机输出是这四个字符串中的某个
25 |
26 | let ranks = [1,2,3,4]
27 | ranks.random!
28 | // 随机输出是这四个数字中的某个
29 |
30 | languages.appendRandomDescription(ranks.random!)
31 | // 随机组合 languages 和 ranks 中的各一个元素,然后输出
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/fatalError.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | enum MyEnum {
5 | case Value1,Value2,Value3
6 | }
7 |
8 |
9 | func check(someValue: MyEnum) -> String {
10 | switch someValue {
11 | case .Value1:
12 | return "OK"
13 | case .Value2:
14 | return "Maybe OK"
15 | default:
16 | // 这个分支没有返回 String,也能编译通过
17 | fatalError("Should not show!")
18 | }
19 | }
20 |
21 | class MyClass {
22 | func methodMustBeImplementedInSubclass() {
23 | fatalError("这个方法必须在子类中被重写")
24 | }
25 | }
26 |
27 | class YourClass: MyClass {
28 | override func methodMustBeImplementedInSubclass() {
29 | print("YourClass 实现了该方法")
30 | }
31 | }
32 |
33 | class TheirClass: MyClass {
34 | func someOtherMethod() {
35 |
36 | }
37 | }
38 |
39 | YourClass().methodMustBeImplementedInSubclass()
40 | // YourClass 实现了该方法
41 |
42 | TheirClass().methodMustBeImplementedInSubclass()
43 | // 这个方法必须在子类中被重写
44 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/fatalError.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/final.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class Parent {
5 |
6 | final func method() {
7 | print("开始配置")
8 | // ..必要的代码
9 |
10 | methodImpl()
11 |
12 | // ..必要的代码
13 | print("结束配置")
14 | }
15 |
16 | func methodImpl() {
17 | fatalError("子类必须实现这个方法")
18 | // 或者也可以给出默认实现
19 | }
20 |
21 | }
22 |
23 | class Child: Parent {
24 | override func methodImpl() {
25 | //..子类的业务逻辑
26 | print("Setup in Child")
27 | }
28 | }
29 |
30 | let c = Child()
31 | c.method()
--------------------------------------------------------------------------------
/Swifter.playground/Pages/final.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/func-dispatch.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class MyClass {
5 | func method(number: Int) -> Int {
6 | return number + 1
7 | }
8 | }
9 |
10 | let object = MyClass()
11 | let result = object.method(number: 1)
12 | // result = 2
13 |
14 |
15 | let f = MyClass.method
16 | let object1 = MyClass()
17 | let result1 = f(object)(1)
18 |
19 |
20 | class MyClass1 {
21 | func method(number: Int) -> Int {
22 | return number + 1
23 | }
24 |
25 | class func method(number: Int) -> Int {
26 | return number
27 | }
28 | }
29 |
30 | let f1 = MyClass1.method
31 | // class func method 的版本
32 |
33 | let f2: (Int) -> Int = MyClass1.method
34 | // 和 f1 相同
35 |
36 | let f3: (MyClass1) -> (Int) -> Int = MyClass1.method
37 | // func method 的柯里化版本
38 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/func-dispatch.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/func-params.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 |
5 | func incrementor1(variable: Int) -> Int {
6 | return variable + 1
7 | }
8 |
9 | let a = incrementor1(variable: 4)
10 |
11 | func incrementor2(variable: Int) -> Int {
12 | var num = variable
13 | num += 1
14 | return num
15 | }
16 |
17 | var luckyNumber = 7
18 | let newNumber = incrementor2(variable: luckyNumber)
19 | // newNumber = 8
20 |
21 | print(luckyNumber)
22 | // luckyNumber 还是 7
23 |
24 | func incrementor3(variable: inout Int) {
25 | variable += 1
26 | }
27 |
28 | luckyNumber = 7
29 | incrementor3(variable: &luckyNumber)
30 |
31 | print(luckyNumber)
32 | // luckyNumber = 8
33 |
34 | func makeIncrementor(addNumber: Int) -> ((inout Int) -> ()) {
35 | func incrementor(variable: inout Int) -> () {
36 | variable += addNumber;
37 | }
38 | return incrementor;
39 | }
40 |
41 | var input = 10
42 | let incrementor = makeIncrementor(addNumber: 2)
43 | incrementor(&input)
44 | print(input)
45 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/func-params.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/gcd-delay.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import PlaygroundSupport
4 |
5 | PlaygroundPage.current.needsIndefiniteExecution = true
6 |
7 | // 创建目标队列
8 | let workingQueue = DispatchQueue(label: "my_queue")
9 |
10 |
11 | // 派发到刚创建的队列中,GCD 会负责进行线程调度
12 |
13 | workingQueue.async {
14 | // 在 workingQueue 中异步进行
15 | print("努力工作")
16 | Thread.sleep(forTimeInterval: 2) // 模拟两秒的执行时间
17 |
18 | DispatchQueue.main.async {
19 | // 返回到主线程更新 UI
20 | print("结束工作,更新 UI")
21 | }
22 | }
23 |
24 | let time: TimeInterval = 2.0
25 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) {
26 | print("2 秒后输出")
27 | }
28 |
29 | import Foundation
30 |
31 | typealias Task = (_ cancel : Bool) -> Void
32 |
33 | func delay(_ time: TimeInterval, task: @escaping ()->()) -> Task? {
34 |
35 | func dispatch_later(block: @escaping ()->()) {
36 | let t = DispatchTime.now() + time
37 | DispatchQueue.main.asyncAfter(deadline: t, execute: block)
38 | }
39 |
40 |
41 |
42 | var closure: (()->Void)? = task
43 | var result: Task?
44 |
45 | let delayedClosure: Task = {
46 | cancel in
47 | if let internalClosure = closure {
48 | if (cancel == false) {
49 | DispatchQueue.main.async(execute: internalClosure)
50 | }
51 | }
52 | closure = nil
53 | result = nil
54 | }
55 |
56 | result = delayedClosure
57 |
58 | dispatch_later {
59 | if let delayedClosure = result {
60 | delayedClosure(false)
61 | }
62 | }
63 |
64 | return result;
65 |
66 | }
67 |
68 | func cancel(_ task: Task?) {
69 | task?(true)
70 | }
71 |
72 | delay(2) { print("2 秒后输出") }
73 |
74 | let task = delay(5) { print("拨打 110") }
75 |
76 | // 仔细想一想..
77 | // 还是取消为妙..
78 | cancel(task)
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/general.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | // Press ⌘1 (Or use View -> Navigators menu) to open Project Navigation to choose the file.
5 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/general.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/hash.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let num = 19
5 | print(num.hashValue) // 19
6 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/hash.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/indirect-nested-enum.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | //class Node {
5 | // let value: T?
6 | // let next: Node?
7 | //
8 | // init(value: T?, next: Node?) {
9 | // self.value = value
10 | // self.next = next
11 | // }
12 | //}
13 | //
14 | //let list = Node(value: 1,
15 | // next: Node(value: 2,
16 | // next: Node(value: 3,
17 | // next: Node(value: 4, next: nil))))
18 |
19 |
20 | indirect enum LinkedList {
21 | case empty
22 | case node(Element, LinkedList)
23 |
24 | func removing(_ element: Element) -> LinkedList {
25 | guard case let .node(value, next) = self else {
26 | return .empty
27 | }
28 | return value == element ?
29 | next : LinkedList.node(value, next.removing(element))
30 | }
31 | }
32 |
33 | let linkedList = LinkedList.node(1, .node(2, .node(3, .node(4, .empty))))
34 | print(linkedList)
35 |
36 | let result1 = linkedList.removing(2)
37 | print(result1)
38 |
39 | let result2 = linkedList.removing(100)
40 | print(result2)
41 |
42 | let emptyList = LinkedList.empty
43 | let result3 = emptyList.removing(12)
44 | print(result3)
45 |
46 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/indirect-nested-enum.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/init-keyword.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 |
5 | class ClassA {
6 | let numA: Int
7 | required init(num: Int) {
8 | numA = num
9 | }
10 |
11 | convenience init(bigNum: Bool) {
12 | self.init(num: bigNum ? 10000 : 1)
13 | }
14 | }
15 |
16 | class ClassB: ClassA {
17 | let numB: Int
18 |
19 | required init(num: Int) {
20 | numB = num + 1
21 | super.init(num: num)
22 | }
23 | }
24 |
25 | let anObj = ClassB(bigNum: true)
26 | // anObj.numA = 10000, anObj.numB = 10001
--------------------------------------------------------------------------------
/Swifter.playground/Pages/init-keyword.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/init-nil.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let url = NSURL(string: "ht tp://swifter。tips")
5 | print(url)
6 |
7 | extension Int {
8 | init?(fromString: String) {
9 | self = 0
10 | var digit = fromString.characters.count - 1
11 | for c in fromString.characters {
12 | var number = 0
13 | if let n = Int(String(c)) {
14 | number = n
15 | } else {
16 | switch c {
17 | case "一": number = 1
18 | case "二": number = 2
19 | case "三": number = 3
20 | case "四": number = 4
21 | case "五": number = 5
22 | case "六": number = 6
23 | case "七": number = 7
24 | case "八": number = 8
25 | case "九": number = 9
26 | case "零": number = 0
27 | default: return nil
28 | }
29 | }
30 |
31 | self = self + number * Int(pow(10, Double(digit)))
32 | digit = digit - 1
33 | }
34 | }
35 | }
36 |
37 | let number1 = Int(fromString: "12")
38 | // {Some 12}
39 |
40 | let number2 = Int(fromString: "三二五")
41 | // {Some 325}
42 |
43 | let number3 = Int(fromString: "七9八")
44 | // {Some 798}
45 |
46 | let number4 = Int(fromString: "吃了么")
47 | // nil
48 |
49 | let number5 = Int(fromString: "1a4n")
50 | // nil
--------------------------------------------------------------------------------
/Swifter.playground/Pages/init-nil.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/init.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | class Cat {
3 | var name: String
4 | init() {
5 | name = "cat"
6 | }
7 | }
8 |
9 | class Tiger: Cat {
10 | let power: Int
11 | override init() {
12 | power = 10
13 | super.init()
14 | name = "tiger"
15 | }
16 | }
17 |
18 | class Cat1 {
19 | var name: String
20 | init() {
21 | name = "cat"
22 | }
23 | }
24 |
25 | class Tiger1: Cat1 {
26 | let power: Int
27 | override init() {
28 | power = 10
29 | // 如果我们不需要打改变 name 的话,
30 | // 虽然我们没有显式地对 super.init() 进行调用
31 | // 不过由于这是初始化的最后了,Swift 替我们自动完成了
32 | }
33 | }
34 |
35 | let cat = Cat1()
36 |
37 | let tiger = Tiger1()
38 |
39 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/init.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/instance-type.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let date1 = NSDate()
5 | let name1: AnyClass! = object_getClass(date1)
6 | print(name1)
7 | // 输出:
8 | // __NSDate
9 |
10 |
11 | let date2 = NSDate()
12 | let name2 = type(of: date2)
13 | print(name2)
14 | // 输出:
15 | // __NSDate
16 |
17 | let string = "Hello"
18 | let name = type(of: string)
19 | print(name)
20 | debugPrint(name)
21 | // 输出:
22 | // Swift.String
23 |
24 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/instance-type.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/intropection.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class ClassA: NSObject { }
5 | class ClassB: ClassA { }
6 |
7 | let obj1: NSObject = ClassB()
8 | let obj2: NSObject = ClassB()
9 |
10 | obj1.isKind(of: ClassA.self) // true
11 | obj2.isMember(of: ClassA.self) // false
12 |
13 | let obj: AnyObject = ClassB()
14 |
15 | if (obj is ClassA) {
16 | print("属于 ClassA")
17 | }
18 |
19 | if (obj is ClassB) {
20 | print("属于 ClassB")
21 | }
22 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/intropection.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/json.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let jsonString = "{\"menu\": {" +
5 | "\"id\": \"file\"," +
6 | "\"value\": \"File\"," +
7 | "\"popup\": {" +
8 | "\"menuitem\": [" +
9 | "{\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"}," +
10 | "{\"value\": \"Open\", \"onclick\": \"OpenDoc()\"}," +
11 | "{\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}" +
12 | "]" +
13 | "}" +
14 | "}}"
15 |
16 | let json: Any = try! JSONSerialization.jsonObject(
17 | with: jsonString.data(using: .utf8, allowLossyConversion: true)!,
18 | options: [])
19 |
20 | if let jsonDic = json as? NSDictionary {
21 | if let menu = jsonDic["menu"] as? [String: AnyObject] {
22 | if let popup: AnyObject = menu["popup"] {
23 | if let popupDic = popup as? [String: AnyObject] {
24 | if let menuItems: AnyObject = popupDic["menuitem"] {
25 | if let menuItemsArr = menuItems as? [AnyObject] {
26 | if let item0 = menuItemsArr[0]
27 | as? [String: AnyObject] {
28 | if let value: AnyObject = item0["value"] {
29 | print(value)
30 | }
31 | }
32 | }
33 | }
34 | }
35 | }
36 | }
37 | }
38 |
39 | if let jsonDic = json as? NSDictionary,
40 | let menu = jsonDic["menu"] as? [String: AnyObject],
41 | let popup = menu["popup"],
42 | let popupDic = popup as? [String: AnyObject],
43 | let menuItems = popupDic["menuitem"],
44 | let menuItemsArr = menuItems as? [AnyObject],
45 | let item0 = menuItemsArr[0] as? [String: AnyObject],
46 | let value = item0["value"]
47 | {
48 | print(value)
49 | }
50 |
51 | if let value = JSON(json)["menu"]["popup"]["menuitem"][0]["value"].string {
52 | print(value)
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/json.xcplaygroundpage/Sources/SwiftyJSON.swift:
--------------------------------------------------------------------------------
1 | // SwiftyJSON.swift
2 | //
3 | // Copyright (c) 2014 Ruoyu Fu, Pinglin Tang
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in
13 | // all copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | // MARK: - Error
26 |
27 | ///Error domain
28 | public let ErrorDomain: String = "SwiftyJSONErrorDomain"
29 |
30 | ///Error code
31 | public let ErrorUnsupportedType: Int = 999
32 | public let ErrorIndexOutOfBounds: Int = 900
33 | public let ErrorWrongType: Int = 901
34 | public let ErrorNotExist: Int = 500
35 | public let ErrorInvalidJSON: Int = 490
36 |
37 | // MARK: - JSON Type
38 |
39 | /**
40 | JSON's type definitions.
41 |
42 | See http://www.json.org
43 | */
44 | public enum Type :Int{
45 |
46 | case number
47 | case string
48 | case bool
49 | case array
50 | case dictionary
51 | case null
52 | case unknown
53 | }
54 |
55 | // MARK: - JSON Base
56 |
57 | public struct JSON {
58 |
59 | /**
60 | Creates a JSON using the data.
61 |
62 | - parameter data: The NSData used to convert to json.Top level object in data is an NSArray or NSDictionary
63 | - parameter opt: The JSON serialization reading options. `.AllowFragments` by default.
64 | - parameter error: error The NSErrorPointer used to return the error. `nil` by default.
65 |
66 | - returns: The created JSON
67 | */
68 | public init(data:Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer? = nil) {
69 | do {
70 | let object: Any = try JSONSerialization.jsonObject(with: data, options: opt)
71 | self.init(object)
72 | } catch let aError as NSError {
73 | if error != nil {
74 | error??.pointee = aError
75 | }
76 | self.init(NSNull())
77 | }
78 | }
79 |
80 | /**
81 | Create a JSON from JSON string
82 | - parameter string: Normal json string like '{"a":"b"}'
83 |
84 | - returns: The created JSON
85 | */
86 | public static func parse(_ string:String) -> JSON {
87 | return string.data(using: String.Encoding.utf8)
88 | .flatMap({JSON(data: $0)}) ?? JSON(NSNull())
89 | }
90 |
91 | /**
92 | Creates a JSON using the object.
93 |
94 | - parameter object: The object must have the following properties: All objects are NSString/String, NSNumber/Int/Float/Double/Bool, NSArray/Array, NSDictionary/Dictionary, or NSNull; All dictionary keys are NSStrings/String; NSNumbers are not NaN or infinity.
95 |
96 | - returns: The created JSON
97 | */
98 | public init(_ object: Any) {
99 | self.object = object
100 | }
101 |
102 | /**
103 | Creates a JSON from a [JSON]
104 |
105 | - parameter jsonArray: A Swift array of JSON objects
106 |
107 | - returns: The created JSON
108 | */
109 | public init(_ jsonArray:[JSON]) {
110 | self.init(jsonArray.map { $0.object })
111 | }
112 |
113 | /**
114 | Creates a JSON from a [String: JSON]
115 |
116 | - parameter jsonDictionary: A Swift dictionary of JSON objects
117 |
118 | - returns: The created JSON
119 | */
120 | public init(_ jsonDictionary:[String: JSON]) {
121 | var dictionary = [String: Any](minimumCapacity: jsonDictionary.count)
122 | for (key, json) in jsonDictionary {
123 | dictionary[key] = json.object
124 | }
125 | self.init(dictionary)
126 | }
127 |
128 | /// fileprivate object
129 | fileprivate var rawArray: [Any] = []
130 | fileprivate var rawDictionary: [String : Any] = [:]
131 | fileprivate var rawString: String = ""
132 | fileprivate var rawNumber: NSNumber = 0
133 | fileprivate var rawNull: NSNull = NSNull()
134 | /// fileprivate type
135 | fileprivate var _type: Type = .null
136 | /// prviate error
137 | fileprivate var _error: NSError? = nil
138 |
139 | /// Object in JSON
140 | public var object: Any {
141 | get {
142 | switch self.type {
143 | case .array:
144 | return self.rawArray
145 | case .dictionary:
146 | return self.rawDictionary
147 | case .string:
148 | return self.rawString
149 | case .number:
150 | return self.rawNumber
151 | case .bool:
152 | return self.rawNumber
153 | default:
154 | return self.rawNull
155 | }
156 | }
157 | set {
158 | _error = nil
159 | switch newValue {
160 | case let number as NSNumber:
161 | if number.isBool {
162 | _type = .bool
163 | } else {
164 | _type = .number
165 | }
166 | self.rawNumber = number
167 | case let string as String:
168 | _type = .string
169 | self.rawString = string
170 | case _ as NSNull:
171 | _type = .null
172 | case let array as [Any]:
173 | _type = .array
174 | self.rawArray = array
175 | case let dictionary as [String : Any]:
176 | _type = .dictionary
177 | self.rawDictionary = dictionary
178 | default:
179 | _type = .unknown
180 | _error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"])
181 | }
182 | }
183 | }
184 |
185 | /// json type
186 | public var type: Type { get { return _type } }
187 |
188 | /// Error in JSON
189 | public var error: NSError? { get { return self._error } }
190 |
191 | /// The static null json
192 | @available(*, unavailable, renamed:"null")
193 | public static var nullJSON: JSON { get { return null } }
194 | public static var null: JSON { get { return JSON(NSNull()) } }
195 | }
196 |
197 | public enum JSONIndex:Comparable {
198 | case array(Int)
199 | case dictionary(DictionaryIndex)
200 | case null
201 | }
202 |
203 | public func ==(lhs: JSONIndex, rhs: JSONIndex) -> Bool {
204 | switch (lhs, rhs) {
205 | case (.array(let left), .array(let right)):
206 | return left == right
207 | case (.dictionary(let left), .dictionary(let right)):
208 | return left == right
209 | default:
210 | return false
211 | }
212 | }
213 |
214 | public func <(lhs: JSONIndex, rhs: JSONIndex) -> Bool {
215 | switch (lhs, rhs) {
216 | case (.array(let left), .array(let right)):
217 | return left < right
218 | case (.dictionary(let left), .dictionary(let right)):
219 | return left < right
220 | default:
221 | return false
222 | }
223 | }
224 |
225 |
226 | extension JSON: Collection {
227 |
228 | public typealias Index = JSONIndex
229 |
230 | public var startIndex: Index{
231 | switch type {
232 | case .array:
233 | return .array(rawArray.startIndex)
234 | case .dictionary:
235 | return .dictionary(dictionaryValue.startIndex)
236 | default:
237 | return .null
238 | }
239 | }
240 |
241 | public var endIndex: Index{
242 | switch type {
243 | case .array:
244 | return .array(rawArray.endIndex)
245 | case .dictionary:
246 | return .dictionary(dictionaryValue.endIndex)
247 | default:
248 | return .null
249 | }
250 | }
251 |
252 | public func index(after i: Index) -> Index {
253 | switch i {
254 | case .array(let idx):
255 | return .array(rawArray.index(after: idx))
256 | case .dictionary(let idx):
257 | return .dictionary(dictionaryValue.index(after: idx))
258 | default:
259 | return .null
260 | }
261 |
262 | }
263 |
264 | public subscript (position: Index) -> (String, JSON) {
265 | switch position {
266 | case .array(let idx):
267 | return (String(idx), JSON(self.rawArray[idx]))
268 | case .dictionary(let idx):
269 | return dictionaryValue[idx]
270 | default:
271 | return ("", JSON.null)
272 | }
273 | }
274 |
275 |
276 | }
277 |
278 | // MARK: - Subscript
279 |
280 | /**
281 | * To mark both String and Int can be used in subscript.
282 | */
283 | public enum JSONKey {
284 | case index(Int)
285 | case key(String)
286 | }
287 |
288 | public protocol JSONSubscriptType {
289 | var jsonKey:JSONKey { get }
290 | }
291 |
292 | extension Int: JSONSubscriptType {
293 | public var jsonKey:JSONKey {
294 | return JSONKey.index(self)
295 | }
296 | }
297 |
298 | extension String: JSONSubscriptType {
299 | public var jsonKey:JSONKey {
300 | return JSONKey.key(self)
301 | }
302 | }
303 |
304 | extension JSON {
305 |
306 | /// If `type` is `.Array`, return json whose object is `array[index]`, otherwise return null json with error.
307 | fileprivate subscript(index index: Int) -> JSON {
308 | get {
309 | if self.type != .array {
310 | var r = JSON.null
311 | r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] failure, It is not an array"])
312 | return r
313 | } else if index >= 0 && index < self.rawArray.count {
314 | return JSON(self.rawArray[index])
315 | } else {
316 | var r = JSON.null
317 | r._error = NSError(domain: ErrorDomain, code:ErrorIndexOutOfBounds , userInfo: [NSLocalizedDescriptionKey: "Array[\(index)] is out of bounds"])
318 | return r
319 | }
320 | }
321 | set {
322 | if self.type == .array {
323 | if self.rawArray.count > index && newValue.error == nil {
324 | self.rawArray[index] = newValue.object
325 | }
326 | }
327 | }
328 | }
329 |
330 | /// If `type` is `.Dictionary`, return json whose object is `dictionary[key]` , otherwise return null json with error.
331 | fileprivate subscript(key key: String) -> JSON {
332 | get {
333 | var r = JSON.null
334 | if self.type == .dictionary {
335 | if let o = self.rawDictionary[key] {
336 | r = JSON(o)
337 | } else {
338 | r._error = NSError(domain: ErrorDomain, code: ErrorNotExist, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] does not exist"])
339 | }
340 | } else {
341 | r._error = self._error ?? NSError(domain: ErrorDomain, code: ErrorWrongType, userInfo: [NSLocalizedDescriptionKey: "Dictionary[\"\(key)\"] failure, It is not an dictionary"])
342 | }
343 | return r
344 | }
345 | set {
346 | if self.type == .dictionary && newValue.error == nil {
347 | self.rawDictionary[key] = newValue.object
348 | }
349 | }
350 | }
351 |
352 | /// If `sub` is `Int`, return `subscript(index:)`; If `sub` is `String`, return `subscript(key:)`.
353 | fileprivate subscript(sub sub: JSONSubscriptType) -> JSON {
354 | get {
355 | switch sub.jsonKey {
356 | case .index(let index): return self[index: index]
357 | case .key(let key): return self[key: key]
358 | }
359 | }
360 | set {
361 | switch sub.jsonKey {
362 | case .index(let index): self[index: index] = newValue
363 | case .key(let key): self[key: key] = newValue
364 | }
365 | }
366 | }
367 |
368 | /**
369 | Find a json in the complex data structuresby using the Int/String's array.
370 |
371 | - parameter path: The target json's path. Example:
372 |
373 | let json = JSON[data]
374 | let path = [9,"list","person","name"]
375 | let name = json[path]
376 |
377 | The same as: let name = json[9]["list"]["person"]["name"]
378 |
379 | - returns: Return a json found by the path or a null json with error
380 | */
381 | public subscript(path: [JSONSubscriptType]) -> JSON {
382 | get {
383 | return path.reduce(self) { $0[sub: $1] }
384 | }
385 | set {
386 | switch path.count {
387 | case 0:
388 | return
389 | case 1:
390 | self[sub:path[0]].object = newValue.object
391 | default:
392 | var aPath = path; aPath.remove(at: 0)
393 | var nextJSON = self[sub: path[0]]
394 | nextJSON[aPath] = newValue
395 | self[sub: path[0]] = nextJSON
396 | }
397 | }
398 | }
399 |
400 | /**
401 | Find a json in the complex data structures by using the Int/String's array.
402 |
403 | - parameter path: The target json's path. Example:
404 |
405 | let name = json[9,"list","person","name"]
406 |
407 | The same as: let name = json[9]["list"]["person"]["name"]
408 |
409 | - returns: Return a json found by the path or a null json with error
410 | */
411 | public subscript(path: JSONSubscriptType...) -> JSON {
412 | get {
413 | return self[path]
414 | }
415 | set {
416 | self[path] = newValue
417 | }
418 | }
419 | }
420 |
421 | // MARK: - LiteralConvertible
422 |
423 | extension JSON: Swift.StringLiteralConvertible {
424 |
425 | public init(stringLiteral value: StringLiteralType) {
426 | self.init(value)
427 | }
428 |
429 | public init(extendedGraphemeClusterLiteral value: StringLiteralType) {
430 | self.init(value)
431 | }
432 |
433 | public init(unicodeScalarLiteral value: StringLiteralType) {
434 | self.init(value)
435 | }
436 | }
437 |
438 | extension JSON: Swift.IntegerLiteralConvertible {
439 |
440 | public init(integerLiteral value: IntegerLiteralType) {
441 | self.init(value)
442 | }
443 | }
444 |
445 | extension JSON: Swift.BooleanLiteralConvertible {
446 |
447 | public init(booleanLiteral value: BooleanLiteralType) {
448 | self.init(value)
449 | }
450 | }
451 |
452 | extension JSON: Swift.FloatLiteralConvertible {
453 |
454 | public init(floatLiteral value: FloatLiteralType) {
455 | self.init(value)
456 | }
457 | }
458 |
459 | extension JSON: Swift.DictionaryLiteralConvertible {
460 |
461 | public init(dictionaryLiteral elements: (String, Any)...) {
462 | self.init(elements.reduce([String : Any](minimumCapacity: elements.count)){(dictionary: [String : Any], element:(String, Any)) -> [String : Any] in
463 | var d = dictionary
464 | d[element.0] = element.1
465 | return d
466 | })
467 | }
468 | }
469 |
470 | extension JSON: Swift.ArrayLiteralConvertible {
471 |
472 | public init(arrayLiteral elements: Any...) {
473 | self.init(elements)
474 | }
475 | }
476 |
477 | extension JSON: Swift.NilLiteralConvertible {
478 |
479 | public init(nilLiteral: ()) {
480 | self.init(NSNull())
481 | }
482 | }
483 |
484 | // MARK: - Raw
485 |
486 | extension JSON: Swift.RawRepresentable {
487 |
488 | public init?(rawValue: Any) {
489 | if JSON(rawValue).type == .unknown {
490 | return nil
491 | } else {
492 | self.init(rawValue)
493 | }
494 | }
495 |
496 | public var rawValue: Any {
497 | return self.object
498 | }
499 |
500 | public func rawData(options opt: JSONSerialization.WritingOptions = JSONSerialization.WritingOptions(rawValue: 0)) throws -> Data {
501 | guard JSONSerialization.isValidJSONObject(self.object) else {
502 | throw NSError(domain: ErrorDomain, code: ErrorInvalidJSON, userInfo: [NSLocalizedDescriptionKey: "JSON is invalid"])
503 | }
504 |
505 | return try JSONSerialization.data(withJSONObject: self.object, options: opt)
506 | }
507 |
508 | public func rawString(_ encoding: String.Encoding = String.Encoding.utf8, options opt: JSONSerialization.WritingOptions = .prettyPrinted) -> String? {
509 | switch self.type {
510 | case .array, .dictionary:
511 | do {
512 | let data = try self.rawData(options: opt)
513 | return String(data: data, encoding: encoding)
514 | } catch _ {
515 | return nil
516 | }
517 | case .string:
518 | return self.rawString
519 | case .number:
520 | return self.rawNumber.stringValue
521 | case .bool:
522 | return self.rawNumber.boolValue.description
523 | case .null:
524 | return "null"
525 | default:
526 | return nil
527 | }
528 | }
529 | }
530 |
531 | // MARK: - Printable, DebugPrintable
532 |
533 | extension JSON: Swift.CustomStringConvertible, Swift.CustomDebugStringConvertible {
534 |
535 | public var description: String {
536 | if let string = self.rawString(options:.prettyPrinted) {
537 | return string
538 | } else {
539 | return "unknown"
540 | }
541 | }
542 |
543 | public var debugDescription: String {
544 | return description
545 | }
546 | }
547 |
548 | // MARK: - Array
549 |
550 | extension JSON {
551 |
552 | //Optional [JSON]
553 | public var array: [JSON]? {
554 | get {
555 | if self.type == .array {
556 | return self.rawArray.map{ JSON($0) }
557 | } else {
558 | return nil
559 | }
560 | }
561 | }
562 |
563 | //Non-optional [JSON]
564 | public var arrayValue: [JSON] {
565 | get {
566 | return self.array ?? []
567 | }
568 | }
569 |
570 | //Optional [Any]
571 | public var arrayObject: [Any]? {
572 | get {
573 | switch self.type {
574 | case .array:
575 | return self.rawArray
576 | default:
577 | return nil
578 | }
579 | }
580 | set {
581 | if let array = newValue {
582 | self.object = array
583 | } else {
584 | self.object = NSNull()
585 | }
586 | }
587 | }
588 | }
589 |
590 | // MARK: - Dictionary
591 |
592 | extension JSON {
593 |
594 | //Optional [String : JSON]
595 | public var dictionary: [String : JSON]? {
596 | if self.type == .dictionary {
597 |
598 | return self.rawDictionary.reduce([String : JSON]()) { (dictionary: [String : JSON], element: (String, Any)) -> [String : JSON] in
599 | var d = dictionary
600 | d[element.0] = JSON(element.1)
601 | return d
602 | }
603 | } else {
604 | return nil
605 | }
606 | }
607 |
608 | //Non-optional [String : JSON]
609 | public var dictionaryValue: [String : JSON] {
610 | return self.dictionary ?? [:]
611 | }
612 |
613 | //Optional [String : Any]
614 | public var dictionaryObject: [String : Any]? {
615 | get {
616 | switch self.type {
617 | case .dictionary:
618 | return self.rawDictionary
619 | default:
620 | return nil
621 | }
622 | }
623 | set {
624 | if let v = newValue {
625 | self.object = v
626 | } else {
627 | self.object = NSNull()
628 | }
629 | }
630 | }
631 | }
632 |
633 | // MARK: - Bool
634 |
635 | extension JSON {
636 |
637 | //Optional bool
638 | public var bool: Bool? {
639 | get {
640 | switch self.type {
641 | case .bool:
642 | return self.rawNumber.boolValue
643 | default:
644 | return nil
645 | }
646 | }
647 | set {
648 | if let newValue = newValue {
649 | self.object = NSNumber(value: newValue)
650 | } else {
651 | self.object = NSNull()
652 | }
653 | }
654 | }
655 |
656 | //Non-optional bool
657 | public var boolValue: Bool {
658 | get {
659 | switch self.type {
660 | case .bool, .number, .string:
661 | return (self.object as AnyObject).boolValue
662 | default:
663 | return false
664 | }
665 | }
666 | set {
667 | self.object = NSNumber(value: newValue)
668 | }
669 | }
670 | }
671 |
672 | // MARK: - String
673 |
674 | extension JSON {
675 |
676 | //Optional string
677 | public var string: String? {
678 | get {
679 | switch self.type {
680 | case .string:
681 | return self.object as? String
682 | default:
683 | return nil
684 | }
685 | }
686 | set {
687 | if let newValue = newValue {
688 | self.object = NSString(string:newValue)
689 | } else {
690 | self.object = NSNull()
691 | }
692 | }
693 | }
694 |
695 | //Non-optional string
696 | public var stringValue: String {
697 | get {
698 | switch self.type {
699 | case .string:
700 | return self.object as? String ?? ""
701 | case .number:
702 | return (self.object as AnyObject).stringValue
703 | case .bool:
704 | return (self.object as? Bool).map { String($0) } ?? ""
705 | default:
706 | return ""
707 | }
708 | }
709 | set {
710 | self.object = NSString(string:newValue)
711 | }
712 | }
713 | }
714 |
715 | // MARK: - Number
716 | extension JSON {
717 |
718 | //Optional number
719 | public var number: NSNumber? {
720 | get {
721 | switch self.type {
722 | case .number, .bool:
723 | return self.rawNumber
724 | default:
725 | return nil
726 | }
727 | }
728 | set {
729 | self.object = newValue ?? NSNull()
730 | }
731 | }
732 |
733 | //Non-optional number
734 | public var numberValue: NSNumber {
735 | get {
736 | switch self.type {
737 | case .string:
738 | let decimal = NSDecimalNumber(string: self.object as? String)
739 | if decimal == NSDecimalNumber.notANumber { // indicates parse error
740 | return NSDecimalNumber.zero
741 | }
742 | return decimal
743 | case .number, .bool:
744 | return self.object as? NSNumber ?? NSNumber(value: 0)
745 | default:
746 | return NSNumber(value: 0.0)
747 | }
748 | }
749 | set {
750 | self.object = newValue
751 | }
752 | }
753 | }
754 |
755 | //MARK: - Null
756 | extension JSON {
757 |
758 | public var null: NSNull? {
759 | get {
760 | switch self.type {
761 | case .null:
762 | return self.rawNull
763 | default:
764 | return nil
765 | }
766 | }
767 | set {
768 | self.object = NSNull()
769 | }
770 | }
771 | public func exists() -> Bool{
772 | if let errorValue = error, errorValue.code == ErrorNotExist{
773 | return false
774 | }
775 | return true
776 | }
777 | }
778 |
779 | //MARK: - URL
780 | extension JSON {
781 |
782 | //Optional URL
783 | public var URL: Foundation.URL? {
784 | get {
785 | switch self.type {
786 | case .string:
787 | if let encodedString_ = self.rawString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) {
788 | return Foundation.URL(string: encodedString_)
789 | } else {
790 | return nil
791 | }
792 | default:
793 | return nil
794 | }
795 | }
796 | set {
797 | self.object = newValue?.absoluteString ?? NSNull()
798 | }
799 | }
800 | }
801 |
802 | // MARK: - Int, Double, Float, Int8, Int16, Int32, Int64
803 |
804 | extension JSON {
805 |
806 | public var double: Double? {
807 | get {
808 | return self.number?.doubleValue
809 | }
810 | set {
811 | if let newValue = newValue {
812 | self.object = NSNumber(value: newValue)
813 | } else {
814 | self.object = NSNull()
815 | }
816 | }
817 | }
818 |
819 | public var doubleValue: Double {
820 | get {
821 | return self.numberValue.doubleValue
822 | }
823 | set {
824 | self.object = NSNumber(value: newValue)
825 | }
826 | }
827 |
828 | public var float: Float? {
829 | get {
830 | return self.number?.floatValue
831 | }
832 | set {
833 | if let newValue = newValue {
834 | self.object = NSNumber(value: newValue)
835 | } else {
836 | self.object = NSNull()
837 | }
838 | }
839 | }
840 |
841 | public var floatValue: Float {
842 | get {
843 | return self.numberValue.floatValue
844 | }
845 | set {
846 | self.object = NSNumber(value: newValue)
847 | }
848 | }
849 |
850 | public var int: Int? {
851 | get {
852 | return self.number?.intValue
853 | }
854 | set {
855 | if let newValue = newValue {
856 | self.object = NSNumber(value: newValue)
857 | } else {
858 | self.object = NSNull()
859 | }
860 | }
861 | }
862 |
863 | public var intValue: Int {
864 | get {
865 | return self.numberValue.intValue
866 | }
867 | set {
868 | self.object = NSNumber(value: newValue)
869 | }
870 | }
871 |
872 | public var uInt: UInt? {
873 | get {
874 | return self.number?.uintValue
875 | }
876 | set {
877 | if let newValue = newValue {
878 | self.object = NSNumber(value: newValue)
879 | } else {
880 | self.object = NSNull()
881 | }
882 | }
883 | }
884 |
885 | public var uIntValue: UInt {
886 | get {
887 | return self.numberValue.uintValue
888 | }
889 | set {
890 | self.object = NSNumber(value: newValue)
891 | }
892 | }
893 |
894 | public var int8: Int8? {
895 | get {
896 | return self.number?.int8Value
897 | }
898 | set {
899 | if let newValue = newValue {
900 | self.object = NSNumber(value: newValue)
901 | } else {
902 | self.object = NSNull()
903 | }
904 | }
905 | }
906 |
907 | public var int8Value: Int8 {
908 | get {
909 | return self.numberValue.int8Value
910 | }
911 | set {
912 | self.object = NSNumber(value: newValue)
913 | }
914 | }
915 |
916 | public var uInt8: UInt8? {
917 | get {
918 | return self.number?.uint8Value
919 | }
920 | set {
921 | if let newValue = newValue {
922 | self.object = NSNumber(value: newValue)
923 | } else {
924 | self.object = NSNull()
925 | }
926 | }
927 | }
928 |
929 | public var uInt8Value: UInt8 {
930 | get {
931 | return self.numberValue.uint8Value
932 | }
933 | set {
934 | self.object = NSNumber(value: newValue)
935 | }
936 | }
937 |
938 | public var int16: Int16? {
939 | get {
940 | return self.number?.int16Value
941 | }
942 | set {
943 | if let newValue = newValue {
944 | self.object = NSNumber(value: newValue)
945 | } else {
946 | self.object = NSNull()
947 | }
948 | }
949 | }
950 |
951 | public var int16Value: Int16 {
952 | get {
953 | return self.numberValue.int16Value
954 | }
955 | set {
956 | self.object = NSNumber(value: newValue)
957 | }
958 | }
959 |
960 | public var uInt16: UInt16? {
961 | get {
962 | return self.number?.uint16Value
963 | }
964 | set {
965 | if let newValue = newValue {
966 | self.object = NSNumber(value: newValue)
967 | } else {
968 | self.object = NSNull()
969 | }
970 | }
971 | }
972 |
973 | public var uInt16Value: UInt16 {
974 | get {
975 | return self.numberValue.uint16Value
976 | }
977 | set {
978 | self.object = NSNumber(value: newValue)
979 | }
980 | }
981 |
982 | public var int32: Int32? {
983 | get {
984 | return self.number?.int32Value
985 | }
986 | set {
987 | if let newValue = newValue {
988 | self.object = NSNumber(value: newValue)
989 | } else {
990 | self.object = NSNull()
991 | }
992 | }
993 | }
994 |
995 | public var int32Value: Int32 {
996 | get {
997 | return self.numberValue.int32Value
998 | }
999 | set {
1000 | self.object = NSNumber(value: newValue)
1001 | }
1002 | }
1003 |
1004 | public var uInt32: UInt32? {
1005 | get {
1006 | return self.number?.uint32Value
1007 | }
1008 | set {
1009 | if let newValue = newValue {
1010 | self.object = NSNumber(value: newValue)
1011 | } else {
1012 | self.object = NSNull()
1013 | }
1014 | }
1015 | }
1016 |
1017 | public var uInt32Value: UInt32 {
1018 | get {
1019 | return self.numberValue.uint32Value
1020 | }
1021 | set {
1022 | self.object = NSNumber(value: newValue)
1023 | }
1024 | }
1025 |
1026 | public var int64: Int64? {
1027 | get {
1028 | return self.number?.int64Value
1029 | }
1030 | set {
1031 | if let newValue = newValue {
1032 | self.object = NSNumber(value: newValue)
1033 | } else {
1034 | self.object = NSNull()
1035 | }
1036 | }
1037 | }
1038 |
1039 | public var int64Value: Int64 {
1040 | get {
1041 | return self.numberValue.int64Value
1042 | }
1043 | set {
1044 | self.object = NSNumber(value: newValue)
1045 | }
1046 | }
1047 |
1048 | public var uInt64: UInt64? {
1049 | get {
1050 | return self.number?.uint64Value
1051 | }
1052 | set {
1053 | if let newValue = newValue {
1054 | self.object = NSNumber(value: newValue)
1055 | } else {
1056 | self.object = NSNull()
1057 | }
1058 | }
1059 | }
1060 |
1061 | public var uInt64Value: UInt64 {
1062 | get {
1063 | return self.numberValue.uint64Value
1064 | }
1065 | set {
1066 | self.object = NSNumber(value: newValue)
1067 | }
1068 | }
1069 | }
1070 |
1071 | //MARK: - Comparable
1072 | extension JSON : Swift.Comparable {}
1073 |
1074 | public func ==(lhs: JSON, rhs: JSON) -> Bool {
1075 |
1076 | switch (lhs.type, rhs.type) {
1077 | case (.number, .number):
1078 | return lhs.rawNumber == rhs.rawNumber
1079 | case (.string, .string):
1080 | return lhs.rawString == rhs.rawString
1081 | case (.bool, .bool):
1082 | return lhs.rawNumber.boolValue == rhs.rawNumber.boolValue
1083 | case (.array, .array):
1084 | return lhs.rawArray as NSArray == rhs.rawArray as NSArray
1085 | case (.dictionary, .dictionary):
1086 | return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary
1087 | case (.null, .null):
1088 | return true
1089 | default:
1090 | return false
1091 | }
1092 | }
1093 |
1094 | public func <=(lhs: JSON, rhs: JSON) -> Bool {
1095 |
1096 | switch (lhs.type, rhs.type) {
1097 | case (.number, .number):
1098 | return lhs.rawNumber <= rhs.rawNumber
1099 | case (.string, .string):
1100 | return lhs.rawString <= rhs.rawString
1101 | case (.bool, .bool):
1102 | return lhs.rawNumber.boolValue == rhs.rawNumber.boolValue
1103 | case (.array, .array):
1104 | return lhs.rawArray as NSArray == rhs.rawArray as NSArray
1105 | case (.dictionary, .dictionary):
1106 | return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary
1107 | case (.null, .null):
1108 | return true
1109 | default:
1110 | return false
1111 | }
1112 | }
1113 |
1114 | public func >=(lhs: JSON, rhs: JSON) -> Bool {
1115 |
1116 | switch (lhs.type, rhs.type) {
1117 | case (.number, .number):
1118 | return lhs.rawNumber >= rhs.rawNumber
1119 | case (.string, .string):
1120 | return lhs.rawString >= rhs.rawString
1121 | case (.bool, .bool):
1122 | return lhs.rawNumber.boolValue == rhs.rawNumber.boolValue
1123 | case (.array, .array):
1124 | return lhs.rawArray as NSArray == rhs.rawArray as NSArray
1125 | case (.dictionary, .dictionary):
1126 | return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary
1127 | case (.null, .null):
1128 | return true
1129 | default:
1130 | return false
1131 | }
1132 | }
1133 |
1134 | public func >(lhs: JSON, rhs: JSON) -> Bool {
1135 |
1136 | switch (lhs.type, rhs.type) {
1137 | case (.number, .number):
1138 | return lhs.rawNumber > rhs.rawNumber
1139 | case (.string, .string):
1140 | return lhs.rawString > rhs.rawString
1141 | default:
1142 | return false
1143 | }
1144 | }
1145 |
1146 | public func <(lhs: JSON, rhs: JSON) -> Bool {
1147 |
1148 | switch (lhs.type, rhs.type) {
1149 | case (.number, .number):
1150 | return lhs.rawNumber < rhs.rawNumber
1151 | case (.string, .string):
1152 | return lhs.rawString < rhs.rawString
1153 | default:
1154 | return false
1155 | }
1156 | }
1157 |
1158 | fileprivate let trueNumber = NSNumber(value: true)
1159 | fileprivate let falseNumber = NSNumber(value: false)
1160 | fileprivate let trueObjCType = String(cString: trueNumber.objCType)
1161 | fileprivate let falseObjCType = String(cString: falseNumber.objCType)
1162 |
1163 | // MARK: - NSNumber: Comparable
1164 |
1165 | extension NSNumber {
1166 | var isBool:Bool {
1167 | get {
1168 | let objCType = String(cString: self.objCType)
1169 | if (self.compare(trueNumber) == ComparisonResult.orderedSame && objCType == trueObjCType)
1170 | || (self.compare(falseNumber) == ComparisonResult.orderedSame && objCType == falseObjCType){
1171 | return true
1172 | } else {
1173 | return false
1174 | }
1175 | }
1176 | }
1177 | }
1178 |
1179 | func ==(lhs: NSNumber, rhs: NSNumber) -> Bool {
1180 | switch (lhs.isBool, rhs.isBool) {
1181 | case (false, true):
1182 | return false
1183 | case (true, false):
1184 | return false
1185 | default:
1186 | return lhs.compare(rhs) == ComparisonResult.orderedSame
1187 | }
1188 | }
1189 |
1190 | func !=(lhs: NSNumber, rhs: NSNumber) -> Bool {
1191 | return !(lhs == rhs)
1192 | }
1193 |
1194 | func <(lhs: NSNumber, rhs: NSNumber) -> Bool {
1195 |
1196 | switch (lhs.isBool, rhs.isBool) {
1197 | case (false, true):
1198 | return false
1199 | case (true, false):
1200 | return false
1201 | default:
1202 | return lhs.compare(rhs) == ComparisonResult.orderedAscending
1203 | }
1204 | }
1205 |
1206 | func >(lhs: NSNumber, rhs: NSNumber) -> Bool {
1207 |
1208 | switch (lhs.isBool, rhs.isBool) {
1209 | case (false, true):
1210 | return false
1211 | case (true, false):
1212 | return false
1213 | default:
1214 | return lhs.compare(rhs) == ComparisonResult.orderedDescending
1215 | }
1216 | }
1217 |
1218 | func <=(lhs: NSNumber, rhs: NSNumber) -> Bool {
1219 |
1220 | switch (lhs.isBool, rhs.isBool) {
1221 | case (false, true):
1222 | return false
1223 | case (true, false):
1224 | return false
1225 | default:
1226 | return lhs.compare(rhs) != ComparisonResult.orderedDescending
1227 | }
1228 | }
1229 |
1230 | func >=(lhs: NSNumber, rhs: NSNumber) -> Bool {
1231 |
1232 | switch (lhs.isBool, rhs.isBool) {
1233 | case (false, true):
1234 | return false
1235 | case (true, false):
1236 | return false
1237 | default:
1238 | return lhs.compare(rhs) != ComparisonResult.orderedAscending
1239 | }
1240 | }
1241 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/kvo.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import PlaygroundSupport
3 |
4 | PlaygroundPage.current.needsIndefiniteExecution = true
5 |
6 | class MyClass: NSObject {
7 | dynamic var date = Date()
8 | }
9 |
10 | class MyClass1: NSObject {
11 | var date = Date()
12 | }
13 |
14 | class MyChildClass: MyClass1 {
15 | dynamic override var date: Date {
16 | get { return super.date }
17 | set { super.date = newValue }
18 | }
19 | }
20 |
21 | private var myContext = 0
22 |
23 | class Class: NSObject {
24 |
25 | var myObject: MyClass!
26 |
27 | override init() {
28 | super.init()
29 | myObject = MyClass()
30 | print("初始化 MyClass,当前日期: \(myObject.date)")
31 | myObject.addObserver(self,
32 | forKeyPath: "date",
33 | options: .new,
34 | context: &myContext)
35 |
36 | delay(3) {
37 | self.myObject.date = Date()
38 | }
39 | }
40 |
41 | override func observeValue(forKeyPath keyPath: String?,
42 | of object: Any?,
43 | change: [NSKeyValueChangeKey : Any]?,
44 | context: UnsafeMutableRawPointer?)
45 | {
46 | if let change = change, context == &myContext {
47 | let newDate = change[.newKey]
48 | print("日期发生变化 \(newDate)")
49 | }
50 | }
51 | }
52 |
53 | let obj = Class()
--------------------------------------------------------------------------------
/Swifter.playground/Pages/kvo.xcplaygroundpage/Sources/delay.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public typealias Task = (_ cancel : Bool) -> Void
4 |
5 | public func delay(_ time: TimeInterval, task: @escaping ()->()) -> Task? {
6 |
7 | func dispatch_later(block: @escaping ()->()) {
8 | let t = DispatchTime.now() + time
9 | DispatchQueue.main.asyncAfter(deadline: t, execute: block)
10 | }
11 |
12 |
13 |
14 | var closure: (()->Void)? = task
15 | var result: Task?
16 |
17 | let delayedClosure: Task = {
18 | cancel in
19 | if let internalClosure = closure {
20 | if (cancel == false) {
21 | DispatchQueue.main.async(execute: internalClosure)
22 | }
23 | }
24 | closure = nil
25 | result = nil
26 | }
27 |
28 | result = delayedClosure
29 |
30 | dispatch_later {
31 | if let delayedClosure = result {
32 | delayedClosure(false)
33 | }
34 | }
35 |
36 | return result;
37 |
38 | }
39 |
40 | func cancel(_ task: Task?) {
41 | task?(true)
42 | }
43 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/lazy.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class ClassA {
5 | lazy var str: String = {
6 | let str = "Hello"
7 | print("只在首次访问输出")
8 | return str
9 | }()
10 | }
11 |
12 | print("Creating object")
13 | let obj = ClassA()
14 |
15 | print("Accessing str")
16 | obj.str
17 |
18 | print("Accessing str again")
19 | obj.str
20 |
21 | let data1 = 1...3
22 | let result1 = data1.map {
23 | (i: Int) -> Int in
24 | print("正在处理 \(i)")
25 | return i * 2
26 | }
27 |
28 | print("准备访问结果")
29 | for i in result1 {
30 | print("操作后结果为 \(i)")
31 | }
32 |
33 | print("操作完毕")
34 |
35 |
36 | let data2 = 1...3
37 | let result2 = data2.lazy.map {
38 | (i: Int) -> Int in
39 | print("正在处理 \(i)")
40 | return i * 2
41 | }
42 |
43 | print("准备访问结果")
44 | for i in result2 {
45 | print("操作后结果为 \(i)")
46 | }
47 |
48 | print("操作完毕")
49 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/lazy.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/literal.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 |
5 | let aNumber = 3
6 | let aString = "Hello"
7 | let aBool = true
8 |
9 | let anArray = [1,2,3]
10 | let aDictionary = ["key1": "value1", "key2": "value2"]
11 |
12 | typealias ALC = ExpressibleByArrayLiteral
13 | typealias BLC = ExpressibleByBooleanLiteral
14 | typealias DLC = ExpressibleByDictionaryLiteral
15 | typealias FLC = ExpressibleByFloatLiteral
16 | typealias NLC = ExpressibleByNilLiteral
17 | typealias ILC = ExpressibleByIntegerLiteral
18 | typealias SLC = ExpressibleByStringLiteral
19 |
20 | enum MyBool: Int {
21 | case myTrue, myFalse
22 | }
23 |
24 | extension MyBool: ExpressibleByBooleanLiteral {
25 | init(booleanLiteral value: Bool) {
26 | self = value ? .myTrue : .myFalse
27 | }
28 | }
29 |
30 | let myTrue: MyBool = true
31 | let myFalse: MyBool = false
32 |
33 | myTrue.rawValue // 0
34 | myFalse.rawValue // 1
35 |
36 | //class Person {
37 | // let name: String
38 | // init(name value: String) {
39 | // self.name = value
40 | // }
41 | //}
42 |
43 | class Person: ExpressibleByStringLiteral {
44 | let name: String
45 | init(name value: String) {
46 | self.name = value
47 | }
48 |
49 | required convenience init(stringLiteral value: String) {
50 | self.init(name: value)
51 | }
52 |
53 | required convenience init(extendedGraphemeClusterLiteral value: String) {
54 | self.init(name: value)
55 | }
56 |
57 | required convenience init(unicodeScalarLiteral value: String) {
58 | self.init(name: value)
59 | }
60 | }
61 |
62 | let p: Person = "xiaoMing"
63 | print(p.name)
64 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/literal.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/local-scope.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import PlaygroundSupport
3 |
4 | func local(_ closure: ()->()) {
5 | closure()
6 | }
7 |
8 | func loadView() {
9 |
10 | let view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
11 | view.backgroundColor = .white
12 |
13 | local {
14 | let titleLabel = UILabel(frame: CGRect(x: 150, y: 30, width: 200, height: 40))
15 | titleLabel.textColor = .red
16 | titleLabel.text = "Title"
17 | view.addSubview(titleLabel)
18 | }
19 |
20 | local {
21 | let textLabel = UILabel(frame: CGRect(x: 150, y: 80, width: 200, height: 40))
22 | textLabel.textColor = .red
23 | textLabel.text = "Text"
24 | view.addSubview(textLabel)
25 | }
26 |
27 | PlaygroundPage.current.liveView = view
28 | }
29 |
30 | loadView()
31 |
32 | let titleLabel: UILabel = {
33 | let label = UILabel(frame: CGRect(x: 150, y: 30, width: 200, height: 40))
34 | label.textColor = .red
35 | label.text = "Title"
36 | return label
37 | }()
--------------------------------------------------------------------------------
/Swifter.playground/Pages/local-scope.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/lock.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func myMethod(anObj: AnyObject!) {
5 | objc_sync_enter(anObj)
6 |
7 | // 在 enter 和 exit 之间 anObj 不会被其他线程改变
8 |
9 | objc_sync_exit(anObj)
10 | }
11 |
12 | func synchronized(_ lock: AnyObject, closure: () -> ()) {
13 | objc_sync_enter(lock)
14 | closure()
15 | objc_sync_exit(lock)
16 | }
17 |
18 | func myMethodLocked(anObj: AnyObject!) {
19 | synchronized(anObj) {
20 | // 在括号内 anObj 不会被其他线程改变
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/log.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func method() {
5 | //...
6 | print("文件名:Test.swift, 方法名:method,这是一条输出")
7 | //...
8 | }
9 |
10 | method()
11 |
12 | func printLog(_ message: T,
13 | file: String = #file,
14 | method: String = #function,
15 | line: Int = #line)
16 | {
17 | print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
18 | }
19 |
20 | // Test.swift
21 | func method1() {
22 | //...
23 | printLog("这是一条输出")
24 | //...
25 | }
26 |
27 | method1()
28 |
29 | func printLogDebug(_ message: T,
30 | file: String = #file,
31 | method: String = #function,
32 | line: Int = #line)
33 | {
34 | #if DEBUG
35 | print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
36 | #endif
37 | }
38 |
39 | func method2() {
40 | //...
41 | printLogDebug("这又是一条输出")
42 | //...
43 | }
44 |
45 | method2()
46 | // No Output
47 |
48 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/math-number.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func circlePerimeter(radius: Double) -> Double {
5 | return 2 * M_PI * radius
6 | }
7 |
8 | func yPosition(dy: Double, angle: Double) -> Double {
9 | return dy * tan(angle)
10 | }
11 |
12 | 1.797693134862315e+308 < Double.infinity // true
13 | 1.797693134862316e+308 < Double.infinity // false
14 |
15 | let a = 0.0 / 0.0
16 | let b = sqrt(-1.0)
17 | let c = 0.0 * Double.infinity
18 |
19 | let num = Double.nan
20 | if num == num {
21 | print("Num is \(num)")
22 | } else {
23 | print("NaN")
24 | }
25 |
26 | // 输出:
27 | // NaN
28 |
29 | if num.isNaN {
30 | print("NaN")
31 | }
32 | // 输出:
33 | // NaN
34 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/math-number.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/memory-retain-cycle.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 |
5 | /// 1
6 | class A: NSObject {
7 | let b: B
8 | override init() {
9 | b = B()
10 | super.init()
11 | b.a = self
12 | }
13 |
14 | deinit {
15 | print("A deinit")
16 | }
17 | }
18 |
19 | class B: NSObject {
20 | weak var a: A? = nil
21 | deinit {
22 | print("B deinit")
23 | }
24 | }
25 |
26 | var obj: A? = A()
27 | obj = nil
28 |
29 |
30 | /// 2
31 | // RequestManager.swift
32 | class RequestManager: RequestHandler {
33 |
34 | @objc func requestFinished() {
35 | print("请求完成")
36 | }
37 |
38 | func sendRequest() {
39 | let req = Request()
40 | req.delegate = self
41 |
42 | req.send()
43 | }
44 | }
45 |
46 | // Request.swift
47 | @objc protocol RequestHandler {
48 | @objc optional func requestFinished()
49 | }
50 |
51 | class Request {
52 | weak var delegate: RequestHandler!;
53 |
54 | func send() {
55 | // 发送请求
56 | // 一般来说会将 req 的引用传递给网络框架
57 | }
58 |
59 | func gotResponse() {
60 | // 请求返回
61 | delegate?.requestFinished?()
62 | }
63 | }
64 |
65 | /// 3
66 | class Person {
67 | let name: String
68 |
69 | // lazy var printName: ()->() = {
70 | // print("The name is \(self.name)")
71 | // }
72 |
73 | lazy var printName: ()->() = {
74 | [weak self] in
75 | if let strongSelf = self {
76 | print("The name is \(strongSelf.name)")
77 | }
78 | }
79 |
80 | init(personName: String) {
81 | name = personName
82 | }
83 |
84 | deinit {
85 | print("Person deinit \(self.name)")
86 | }
87 | }
88 |
89 | var xiaoMing: Person? = Person(personName: "XiaoMing")
90 | xiaoMing!.printName()
91 | xiaoMing = nil
92 |
93 | // 输出:
94 | // The name is XiaoMing
95 | // Person deinit XiaoMing
96 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/multi-collection.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let numbers = [1,2,3,4,5]
5 | // numbers 的类型是 [Int]
6 |
7 | let strings = ["hello", "world"]
8 | // strings 的类型是 [String]
9 |
10 | import UIKit
11 |
12 | // [Any]
13 | let mixed1: [Any] = [1, "two", 3]
14 |
15 | // [NSObject]
16 | let objectArray = [1 as NSObject, "two" as NSObject, 3 as NSObject]
17 |
18 | let any = mixed1[0] // Any 类型
19 | let nsObject = objectArray[0] // NSObject 类型
20 |
21 | let mixed2: [CustomStringConvertible] = [1, "two", 3]
22 |
23 | for obj in mixed2 {
24 | print(obj.description)
25 | }
26 |
27 | enum IntOrString {
28 | case IntValue(Int)
29 | case StringValue(String)
30 | }
31 |
32 | let mixed3 = [IntOrString.IntValue(1),
33 | IntOrString.StringValue("two"),
34 | IntOrString.IntValue(3)]
35 |
36 | for value in mixed3 {
37 | switch value {
38 | case let .IntValue(i):
39 | print(i * 2)
40 | case let .StringValue(s):
41 | print(s.capitalized)
42 | }
43 | }
44 |
45 | // 输出:
46 | // 2
47 | // Two
48 | // 6
49 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/multi-collection.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/multi-method.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class Pet {}
5 | class Cat: Pet {}
6 | class Dog: Pet {}
7 |
8 | func printPet(_ pet: Pet) {
9 | print("Pet")
10 | }
11 |
12 | func printPet(_ cat: Cat) {
13 | print("Meow")
14 | }
15 |
16 | func printPet(_ dog: Dog) {
17 | print("Bark")
18 | }
19 |
20 | printPet(Cat()) // Meow
21 | printPet(Dog()) // Bark
22 | printPet(Pet()) // Pet
23 |
24 | func printThem(_ pet: Pet, _ cat: Cat) {
25 | printPet(pet)
26 | printPet(cat)
27 | }
28 |
29 | printThem(Dog(), Cat())
30 |
31 | // 输出:
32 | // Pet
33 | // Meow
34 |
35 | func printThemAgain(_ pet: Pet, _ cat: Cat) {
36 | if let aCat = pet as? Cat {
37 | printPet(aCat)
38 | } else if let aDog = pet as? Dog {
39 | printPet(aDog)
40 | }
41 | printPet(cat)
42 | }
43 |
44 | printThemAgain(Dog(), Cat())
45 | // 输出:
46 | // Bark
47 | // Meow
48 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/multiple-optional.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | var string: String? = "string"
5 | var anotherString: String?? = string
6 |
7 | var literalOptional: String?? = "string"
8 |
9 | var aNil: String? = nil
10 |
11 | var anotherNil: String?? = aNil
12 | var literalNil: String?? = nil
13 |
14 | if let a = anotherNil {
15 | // This will output.
16 | print("anotherNil")
17 | }
18 |
19 | if let b = literalNil {
20 | // This will not output.
21 | print("literalNil")
22 | }
23 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/nsnull.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | // 假设 jsonValue 是从一个 JSON 中取出的 NSNull
5 | let jsonValue: AnyObject = NSNull()
6 |
7 | if let string = jsonValue as? String {
8 | print(string.hasPrefix("a"))
9 | } else {
10 | print("不能解析")
11 | }
12 |
13 | // 输出:
14 | // 不能解析
15 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/nsnull.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/objc-dynamic.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | @objc(MyClass)
5 | class 我的类: NSObject {
6 | @objc(greeting:)
7 | func 打招呼(名字: String) {
8 | print("哈喽,\(名字)")
9 | }
10 | }
11 |
12 | 我的类().打招呼(名字: "小明")
--------------------------------------------------------------------------------
/Swifter.playground/Pages/objc-protocol.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 |
5 | @objc protocol OptionalProtocol1 {
6 | @objc optional func optionalMethod()
7 | }
8 |
9 | @objc protocol OptionalProtocol2 {
10 | @objc optional func optionalMethod() // 可选
11 | func necessaryMethod() // 必须
12 | @objc optional func anotherOptionalMethod() // 可选
13 | }
14 |
15 | class MyClass1: OptionalProtocol1 {
16 |
17 | }
18 |
19 | //class MyClass2: OptionalProtocol2 {
20 | // func necessaryMethod() {
21 | // print("Default Implementation")
22 | // }
23 | //}
24 |
25 | class MyClass2: NSObject, OptionalProtocol2 {
26 | func necessaryMethod() {
27 | print("Implemented in Class2")
28 | }
29 | }
30 |
31 |
32 | protocol OptionalProtocol3 {
33 | func optionalMethod() // 可选
34 | func necessaryMethod() // 必须
35 | func anotherOptionalMethod() // 可选
36 | }
37 |
38 | extension OptionalProtocol3 {
39 | func optionalMethod() {
40 | print("Implemented in extension")
41 | }
42 |
43 | func anotherOptionalMethod() {
44 | print("Implemented in extension")
45 | }
46 | }
47 |
48 | class MyClass3: OptionalProtocol3 {
49 | func necessaryMethod() {
50 | print("Implemented in Class3")
51 | }
52 |
53 | func optionalMethod() {
54 | print("Implemented in Class3")
55 | }
56 | }
57 |
58 | let obj = MyClass3()
59 | obj.necessaryMethod()
60 | obj.optionalMethod()
61 | obj.anotherOptionalMethod()
62 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/operator.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | struct Vector2D {
5 | var x = 0.0
6 | var y = 0.0
7 | }
8 |
9 | let v1 = Vector2D(x: 2.0, y: 3.0)
10 | let v2 = Vector2D(x: 1.0, y: 4.0)
11 | let v3 = Vector2D(x: v1.x + v2.x, y: v1.y + v2.y)
12 | // v3 为 {x 3.0, y 7.0}
13 |
14 | func +(left: Vector2D, right: Vector2D) -> Vector2D {
15 | return Vector2D(x: left.x + right.x, y: left.y + right.y)
16 | }
17 |
18 | let v4 = v1 + v2
19 | // v4 为 {x 3.0, y 7.0}
20 |
21 | precedencegroup DotProductPrecedence {
22 | associativity: none
23 | higherThan: MultiplicationPrecedence
24 | }
25 |
26 | infix operator +*: DotProductPrecedence
27 |
28 | func +* (left: Vector2D, right: Vector2D) -> Double {
29 | return left.x * right.x + left.y * right.y
30 | }
31 |
32 | let result = v1 +* v2
33 | // 输出为 14.0
34 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/operator.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/optional-chaining.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 |
5 | class Toy {
6 | let name: String
7 | init(name: String) {
8 | self.name = name
9 | }
10 | }
11 |
12 | class Pet {
13 | var toy: Toy?
14 | }
15 |
16 | class Child {
17 | var pet: Pet?
18 | }
19 |
20 | let xiaoming = Child()
21 |
22 | let toyName = xiaoming.pet?.toy?.name
23 |
24 | if let toyName = xiaoming.pet?.toy?.name {
25 | // 太好了,小明既有宠物,而且宠物还正好有个玩具
26 | }
27 |
28 | extension Toy {
29 | func play() {
30 | //...
31 | }
32 | }
33 |
34 | xiaoming.pet?.toy?.play()
35 |
36 | //let playClosure = {(child: Child) -> () in child.pet?.toy?.play()} //返回值将永远不为 nil
37 | let playClosure = {(child: Child) -> ()? in child.pet?.toy?.play()}
38 |
39 | if let result: () = playClosure(xiaoming) {
40 | print("好开心~")
41 | } else {
42 | print("没有玩具可以玩 :(")
43 | }
--------------------------------------------------------------------------------
/Swifter.playground/Pages/optional-chaining.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/optional-map.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let arr = [1,2,3]
5 | let doubled = arr.map{
6 | $0 * 2
7 | }
8 |
9 | print(doubled)
10 | // 输出:
11 | // [2,4,6]
12 |
13 | let num: Int? = 3
14 | let result = num.map {
15 | $0 * 2
16 | }
17 |
18 | result
19 | // result 为 {Some 6}
--------------------------------------------------------------------------------
/Swifter.playground/Pages/optional-map.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/options.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | UIView.animate(withDuration: 0.3,
5 | delay: 0.0,
6 | options: [.curveEaseIn, .allowUserInteraction],
7 | animations: {},
8 | completion: nil)
9 |
10 | struct YourOption: OptionSet {
11 | let rawValue: UInt
12 | static let none = YourOption(rawValue: 0)
13 | static let option1 = YourOption(rawValue: 1)
14 | static let option2 = YourOption(rawValue: 1 << 1)
15 | //...
16 | }
17 |
18 | YourOption.option1
19 |
20 | [YourOption.option1, YourOption.option2]
21 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/options.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/output-format.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let a = 3;
5 | let b = 1.234567 // 我们在这里不去区分 float 和 Double 了
6 | let c = "Hello"
7 | print("int:\(a) double:\(b) string:\(c)")
8 | // 输出:
9 | // int:3 double:1.234567 string:Hello
10 |
11 | let format = String(format:"%.2f",b)
12 | print("double:\(format)")
13 | // 输出:
14 | // double:1.23
15 |
16 | extension Double {
17 | func format(_ f: String) -> String {
18 | return String(format: "%\(f)f", self)
19 | }
20 | }
21 |
22 | let f = ".2"
23 | print("double:\(b.format(f))")
24 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/overflow.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class MyClass {
5 | var a: Int = 1
6 | func method() {
7 | a = a * 100000
8 | a = a * 100000
9 | a = a * 100000
10 | print(a)
11 | }
12 | }
13 |
14 | MyClass().method()
15 |
16 | // 64 位环境 (iPhone 5s 及以上)
17 | // 1,000,000,000,000,000
18 |
19 | // 32 位环境 (iPhone 5c 及以下)
20 | // 崩溃
21 |
22 | //func method() {
23 | // var max = Int.max
24 | // max = max + 1
25 | //}
26 |
27 | var max = Int.max
28 | max = max &+ 1
29 |
30 | // 64 位系统下
31 | // max = -9,223,372,036,854,775,808
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/overflow.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/pattern-match.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 |
5 | let password = "akfuv(3"
6 | switch password {
7 | case "akfuv(3": print("密码通过")
8 | default: print("验证失败")
9 | }
10 |
11 | let num: Int? = nil
12 | switch num {
13 | case nil: print("没值")
14 | default: print("\(num!)")
15 | }
16 |
17 | let x = 0.5
18 | switch x {
19 | case -1.0...1.0: print("区间内")
20 | default: print("区间外")
21 | }
22 |
23 | func ~=(pattern: NSRegularExpression, input: String) -> Bool {
24 | return pattern.numberOfMatches(in: input,
25 | options: [],
26 | range: NSRange(location: 0, length: input.characters.count)) > 0
27 | }
28 |
29 | prefix operator ~/
30 |
31 | prefix func ~/(pattern: String) throws -> NSRegularExpression {
32 | return try NSRegularExpression(pattern: pattern, options: [])
33 | }
34 |
35 | let contact = ("http://onevcat.com", "onev@onevcat.com")
36 |
37 | let mailRegex: NSRegularExpression
38 | let siteRegex: NSRegularExpression
39 |
40 | mailRegex = try ~/"^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$"
41 | siteRegex = try ~/"^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$"
42 |
43 | switch contact {
44 | case (siteRegex, mailRegex): print("同时拥有有效的网站和邮箱")
45 | case (_, mailRegex): print("只拥有有效的邮箱")
46 | case (siteRegex, _): print("只拥有有效的网站")
47 | default: print("嘛都没有")
48 | }
49 |
50 | // 输出
51 | // 同时拥有网站和邮箱
52 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/playground-delay.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import PlaygroundSupport
4 |
5 | PlaygroundPage.current.needsIndefiniteExecution = true
6 |
7 | class MyClass {
8 | @objc func callMe() {
9 | print("Hi")
10 | }
11 | }
12 |
13 | let object = MyClass()
14 |
15 | Timer.scheduledTimer(timeInterval: 1, target: object,
16 | selector: #selector(MyClass.callMe), userInfo: nil, repeats: true)
17 |
18 | let url = URL(string: "http://httpbin.org/get")!
19 |
20 | let getTask = URLSession.shared.dataTask(with: url) {
21 | (data, response, error) in
22 | let dictionary = try! JSONSerialization.jsonObject(with: data!, options: [])
23 |
24 | print(dictionary)
25 | }
26 |
27 | getTask.resume()
--------------------------------------------------------------------------------
/Swifter.playground/Pages/playground-liveview.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 | import PlaygroundSupport
4 |
5 |
6 | class ViewController: UITableViewController {
7 | override func viewDidLoad() {
8 | super.viewDidLoad()
9 | view.backgroundColor = .cyan
10 | }
11 | }
12 |
13 | extension ViewController {
14 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
15 | return 30
16 | }
17 |
18 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
19 | let cell = UITableViewCell()
20 | cell.textLabel?.text = String(indexPath.row)
21 | return cell
22 | }
23 | }
24 |
25 | extension ViewController {
26 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
27 | print("Select: \(indexPath.row)")
28 | }
29 | }
30 |
31 | //let label = UILabel(frame: CGRect(x: 0, y: 0, width: 400, height: 200))
32 | //label.backgroundColor = .white
33 | //label.font = UIFont.systemFont(ofSize: 32)
34 | //label.textAlignment = .center
35 | //label.text = "Hello World"
36 | //PlaygroundPage.current.liveView = label
37 |
38 |
39 | let vc = ViewController()
40 | PlaygroundPage.current.liveView = vc
41 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/playground-liveview.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/pointer-memory.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class MyClass {
5 | var a = 1
6 | deinit {
7 | print("deinit")
8 | }
9 | }
10 |
11 | var pointer: UnsafeMutablePointer!
12 |
13 | pointer = UnsafeMutablePointer.allocate(capacity: 1)
14 | pointer.initialize(to: MyClass())
15 |
16 | print(pointer.pointee.a)
17 | pointer.deinitialize()
18 | pointer.deallocate(capacity: 1)
19 | pointer = nil
20 |
21 | // 输出:
22 | // 1
23 | // deinit
24 |
25 | var x:UnsafeMutablePointer!
26 | var t = time_t()
27 | time(&t)
28 | x = localtime(&t)
29 | x = nil
30 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/pointer-memory.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/print.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class MyClass {
5 | var num: Int
6 | init() {
7 | num = 1
8 | }
9 | }
10 |
11 | let obj = MyClass()
12 | print(obj)
13 |
14 | struct Meeting {
15 | var date: NSDate
16 | var place: String
17 | var attendeeName: String
18 | }
19 |
20 | let meeting = Meeting(date: NSDate(timeIntervalSinceNow: 86400),
21 | place: "会议室B1",
22 | attendeeName: "小明")
23 | print(meeting)
24 | // 输出:
25 | // Meeting(date: 2015-08-10 03:15:55 +0000, place: "会议室B1", attendeeName: "小明")
26 |
27 | extension Meeting: CustomStringConvertible {
28 | var description: String {
29 | return "于 \(self.date) 在 \(self.place) 与 \(self.attendeeName) 进行会议"
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/print.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/property-observer.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class MyClass {
5 |
6 | let oneYearInSecond: TimeInterval = 365 * 24 * 60 * 60
7 |
8 | var date: NSDate {
9 | willSet {
10 | let d = date
11 | print("即将将日期从 \(d) 设定至 \(newValue)")
12 | }
13 |
14 | didSet {
15 | if (date.timeIntervalSinceNow > oneYearInSecond) {
16 | print("设定的时间太晚了!")
17 | date = NSDate().addingTimeInterval(oneYearInSecond)
18 | }
19 | print("已经将日期从 \(oldValue) 设定至 \(date)")
20 | }
21 | }
22 |
23 | init() {
24 | date = NSDate()
25 | }
26 | }
27 |
28 | let foo = MyClass()
29 | foo.date = foo.date.addingTimeInterval(10086)
30 |
31 | // 输出
32 | // 即将将日期从 2014-08-23 12:47:36 +0000 设定至 2014-08-23 15:35:42 +0000
33 | // 已经将日期从 2014-08-23 12:47:36 +0000 设定至 2014-08-23 15:35:42 +0000
34 |
35 | // 365 * 24 * 60 * 60 = 31_536_000
36 | foo.date = foo.date.addingTimeInterval(100_000_000)
37 |
38 | // 输出
39 | // 即将将日期从 2014-08-23 13:24:14 +0000 设定至 2017-10-23 23:10:54 +0000
40 | // 设定的时间太晚了!
41 | // 已经将日期从 2014-08-23 13:24:14 +0000 设定至 2015-08-23 13:24:14 +0000
42 |
43 | class A {
44 | var number :Int {
45 | get {
46 | print("get")
47 | return 1
48 | }
49 |
50 | set {print("set")}
51 | }
52 | }
53 |
54 | class B: A {
55 | override var number: Int {
56 | willSet {print("willSet")}
57 | didSet {print("didSet")}
58 | }
59 | }
60 |
61 | let b = B()
62 | b.number = 0
63 |
64 | // 输出
65 | // get
66 | // willSet
67 | // set
68 | // didSet
69 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/protocol-extension.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | protocol MyProtocol {
5 | func method()
6 | }
7 |
8 | extension MyProtocol {
9 | func method() {
10 | print("Called in extension")
11 | }
12 | }
13 |
14 | //struct MyStruct: MyProtocol {
15 | //
16 | //}
17 | //MyStruct().method()
18 | //// 输出:
19 | //// Called in extension
20 |
21 | struct MyStruct: MyProtocol {
22 | func method() {
23 | print("Called in struct")
24 | }
25 | }
26 | MyStruct().method()
27 | // 输出:
28 | // Called in struct
29 |
30 | protocol A1 {
31 | func method1() -> String
32 | }
33 |
34 | struct B1: A1 {
35 | func method1() -> String {
36 | return "hello"
37 | }
38 | }
39 |
40 | let b1 = B1()
41 | b1.method1()
42 |
43 | let a1: A1 = B1()
44 | a1.method1()
45 |
46 | protocol A2 {
47 | func method1() -> String
48 | }
49 |
50 | extension A2 {
51 | func method1() -> String {
52 | return "hi"
53 | }
54 |
55 | func method2() -> String {
56 | return "hi"
57 | }
58 | }
59 |
60 | struct B2: A2 {
61 | func method1() -> String {
62 | return "hello"
63 | }
64 |
65 | func method2() -> String {
66 | return "hello"
67 | }
68 | }
69 |
70 | let b2 = B2()
71 |
72 | b2.method1()
73 | b2.method2()
74 |
75 | let a2 = b2 as A2
76 |
77 | a2.method1()
78 |
79 |
80 | a2.method2()
81 |
82 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/protocol-extension.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/protocol-mutating.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | protocol Vehicle
5 | {
6 | var numberOfWheels: Int {get}
7 | var color: UIColor {get set}
8 |
9 | mutating func changeColor()
10 | }
11 |
12 | struct MyCar: Vehicle {
13 | let numberOfWheels = 4
14 | var color = UIColor.blue
15 |
16 | mutating func changeColor() {
17 | color = .red
18 | }
19 | }
20 |
21 | var car = MyCar()
22 | car.color
23 |
24 | car.changeColor()
25 | car.color
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/protocol-mutating.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/random-number.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let diceFaceCount: UInt32 = 6
5 | let randomRoll = Int(arc4random_uniform(diceFaceCount)) + 1
6 | print(randomRoll)
7 |
8 | func random(in range: Range) -> Int {
9 | let count = UInt32(range.upperBound - range.lowerBound)
10 | return Int(arc4random_uniform(count)) + range.lowerBound
11 | }
12 |
13 | for _ in 0...100 {
14 | let range = Range(1...6)
15 | print(random(in: range))
16 | }
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/range.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | for i in 0...3 {
5 | print(i, terminator: "")
6 | }
7 | //输出 0123
8 |
9 | let test = "helLo"
10 | let interval = "a"..."z"
11 | for c in test.characters {
12 | if !interval.contains(String(c)) {
13 | print("\(c) 不是小写字母")
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/range.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/reflect.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | struct Person {
5 | let name: String
6 | let age: Int
7 | }
8 |
9 | let xiaoMing = Person(name: "XiaoMing", age: 16)
10 | let r = Mirror(reflecting: xiaoMing) // r 是 MirrorType
11 |
12 | print("xiaoMing 是 \(r.displayStyle!)")
13 |
14 | print("属性个数:\(r.children.count)")
15 |
16 | for child in r.children {
17 | print("属性名:\(child.label),值:\(child.value)")
18 | }
19 |
20 | //for i in r.children.startIndex.. Any? {
37 | let mirror = Mirror(reflecting: object)
38 |
39 | for child in mirror.children {
40 | let (targetKey, targetMirror) = (child.label, child.value)
41 | if key == targetKey {
42 | return targetMirror
43 | }
44 | }
45 |
46 | return nil
47 | }
48 |
49 | // 接上面的 xiaoMing
50 | if let name = valueFrom(xiaoMing, key: "name") as? String {
51 | print("通过 key 得到值: \(name)")
52 | }
53 |
54 | // 输出:
55 | // 通过 key 得到值: XiaoMing
56 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/reflect.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/regex.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | struct RegexHelper {
5 | let regex: NSRegularExpression
6 |
7 | init(_ pattern: String) throws {
8 | try regex = NSRegularExpression(pattern: pattern,
9 | options: .caseInsensitive)
10 | }
11 |
12 | func match(_ input: String) -> Bool {
13 | let matches = regex.matches(in: input,
14 | options: [],
15 | range: NSMakeRange(0, input.utf16.count))
16 | return matches.count > 0
17 | }
18 | }
19 |
20 | let mailPattern =
21 | "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$"
22 |
23 | let matcher: RegexHelper
24 | do {
25 | matcher = try RegexHelper(mailPattern)
26 | }
27 |
28 | let maybeMailAddress = "onev@onevcat.com"
29 |
30 | if matcher.match(maybeMailAddress) {
31 | print("有效的邮箱地址")
32 | }
33 | // 输出:
34 | // 有效的邮箱地址
35 |
36 |
37 | precedencegroup MatchPrecedence {
38 | associativity: none
39 | higherThan: DefaultPrecedence
40 | }
41 |
42 | infix operator =~: MatchPrecedence
43 |
44 | func =~(lhs: String, rhs: String) -> Bool {
45 | do {
46 | return try RegexHelper(rhs).match(lhs)
47 | } catch _ {
48 | return false
49 | }
50 | }
51 |
52 | if "onev@onevcat.com" =~
53 | "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$" {
54 | print("有效的邮箱地址")
55 | }
56 | // 输出:
57 | // 有效的邮箱地址
58 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/selector.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class MyObject: NSObject {
4 | func callMe() {
5 | //...
6 | }
7 |
8 | func callMeWithParam(obj: AnyObject!) {
9 | //...
10 | }
11 |
12 | func turn(by angle: Int, speed: Float) {
13 | //...
14 | }
15 |
16 | func selectors() -> [Selector] {
17 | let someMethod = #selector(callMe)
18 | let anotherMethod = #selector(callMeWithParam(obj:))
19 | let method = #selector(turn(by:speed:))
20 |
21 | return [someMethod, anotherMethod, method]
22 | }
23 |
24 | func otherSelectors() -> [Selector] {
25 | let someMethod = #selector(callMe)
26 | let anotherMethod = #selector(callMeWithParam)
27 | let method = #selector(turn)
28 |
29 | return [someMethod, anotherMethod, method]
30 | }
31 |
32 |
33 | func commonFunc() {
34 |
35 | }
36 |
37 | func commonFunc(input: Int) -> Int {
38 | return input
39 | }
40 |
41 | func sameNameSelectors() -> [Selector] {
42 | let method1 = #selector(commonFunc as ()->())
43 | let method2 = #selector(commonFunc as (Int)->Int)
44 | return [method1, method2]
45 | }
46 | }
47 |
48 | let selectors = MyObject().selectors()
49 | print(selectors)
50 |
51 | let otherSelectors = MyObject().otherSelectors()
52 | print(otherSelectors)
53 |
54 | let sameNameSelectors = MyObject().sameNameSelectors()
55 | print(sameNameSelectors)
56 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/self-anyclass.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | class A {
5 | class func method() {
6 | print("Hello")
7 | }
8 | }
9 |
10 | let typeA: A.Type = A.self
11 | typeA.method()
12 |
13 | // 或者
14 | let anyClass: AnyClass = A.self
15 | (anyClass as! A.Type).method()
16 |
17 |
18 | import UIKit
19 | class MusicViewController: UIViewController {
20 |
21 | }
22 |
23 | class AlbumViewController: UIViewController {
24 |
25 | }
26 |
27 | let usingVCTypes: [AnyClass] = [MusicViewController.self,
28 | AlbumViewController.self]
29 |
30 | func setupViewControllers(_ vcTypes: [AnyClass]) {
31 | for vcType in vcTypes {
32 | if vcType is UIViewController.Type {
33 | let vc = (vcType as! UIViewController.Type).init()
34 | print(vc)
35 | }
36 |
37 | }
38 | }
39 |
40 | setupViewControllers(usingVCTypes)
41 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/self-anyclass.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/sequence.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | // 先定义一个实现了 IteratorProtocol 协议的类型
5 | // IteratorProtocol 需要指定一个 typealias Element
6 | // 以及提供一个返回 Element? 的方法 next()
7 | class ReverseIterator: IteratorProtocol {
8 | typealias Element = T
9 |
10 | var array: [Element]
11 | var currentIndex = 0
12 |
13 | init(array: [Element]) {
14 | self.array = array
15 | currentIndex = array.count - 1
16 | }
17 |
18 | func next() -> Element? {
19 | if currentIndex < 0{
20 | return nil
21 | }
22 | else {
23 | let element = array[currentIndex]
24 | currentIndex -= 1
25 | return element
26 | }
27 | }
28 | }
29 |
30 | // 然后我们来定义 Sequence
31 | // 和 IteratorProtocol 很类似,不过换成指定一个 typealias Iterator
32 | // 以及提供一个返回 Iterator? 的方法 makeIterator()
33 | struct ReverseSequence: Sequence {
34 | var array: [T]
35 |
36 | init (array: [T]) {
37 | self.array = array
38 | }
39 |
40 | typealias Iterator = ReverseIterator
41 |
42 | func makeIterator() -> ReverseIterator {
43 | return ReverseIterator(array: self.array)
44 | }
45 | }
46 |
47 | let arr = [0,1,2,3,4]
48 |
49 | // 对 Sequence 可以使用 for...in 来循环访问
50 | for i in ReverseSequence(array: arr) {
51 | print("Index \(i) is \(arr[i])")
52 | }
53 |
54 |
55 | var iterator = arr.makeIterator()
56 | while let obj = iterator.next() {
57 | print(obj)
58 | }
59 |
60 | let aaa = ReverseSequence(array: arr)
61 | aaa.map { (Int) -> Int in
62 | return 1
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/singleton.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | #if swift(>=3.0)
5 | #else
6 | // This is only for Swift 2.3 and earlier
7 | class MyManager1 {
8 | class var shared : MyManager1 {
9 | struct Static {
10 | static var onceToken : dispatch_once_t = 0
11 | static var staticInstance : MyManager1? = nil
12 | }
13 |
14 | dispatch_once(&Static.onceToken) {
15 | Static.staticInstance = MyManager1()
16 | }
17 |
18 | return Static.staticInstance!
19 | }
20 | }
21 |
22 | MyManager1.shared
23 |
24 | #endif
25 |
26 | class MyManager2 {
27 | private static let sharedInstance = MyManager2()
28 | class var sharedManager : MyManager2 {
29 | return sharedInstance
30 | }
31 | }
32 |
33 | MyManager2.sharedManager
34 |
35 | class MyManager3 {
36 | class var sharedManager : MyManager3 {
37 | return sharedInstance
38 | }
39 | }
40 | private let sharedInstance = MyManager3()
41 |
42 | MyManager3.sharedManager
43 |
44 | class MyManager {
45 | static let sharedManager = MyManager()
46 | private init() {}
47 | }
48 |
49 | MyManager.sharedManager
50 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/singleton.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/static-class.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | struct Point {
5 | let x: Double
6 | let y: Double
7 |
8 | // 存储属性
9 | static let zero = Point(x: 0, y: 0)
10 |
11 | // 计算属性
12 | static var ones: [Point] {
13 | return [Point(x: 1, y: 1),
14 | Point(x: -1, y: 1),
15 | Point(x: 1, y: -1),
16 | Point(x: -1, y: -1)]
17 | }
18 |
19 | // 类型方法
20 | static func add(p1: Point, p2: Point) -> Point {
21 | return Point(x: p1.x + p2.x, y: p1.y + p2.y)
22 | }
23 | }
24 |
25 | Point.zero
26 |
27 | Point.ones
28 |
29 | Point.add(p1: Point.zero, p2: Point.ones.first!)
30 |
31 | class MyClass1 {
32 | static var bar: String?
33 | }
34 |
35 | protocol MyProtocol {
36 | static func foo() -> String
37 | }
38 |
39 | struct MyStruct: MyProtocol {
40 | static func foo() -> String {
41 | return "MyStruct"
42 | }
43 | }
44 |
45 | enum MyEnum: MyProtocol {
46 | static func foo() -> String {
47 | return "MyEnum"
48 | }
49 | }
50 |
51 | class MyClass: MyProtocol {
52 | // 在 class 中可以使用 class
53 | class func foo() -> String {
54 | return "MyClass.foo()"
55 | }
56 |
57 | // 也可以使用 static
58 | static func bar() -> String {
59 | return "MyClass.bar()"
60 | }
61 | }
62 |
63 | MyClass.foo()
64 | MyClass.bar()
65 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/static-class.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/string-nsstring.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let levels = "ABCDE"
5 | for i in levels.characters {
6 | print(i)
7 | }
8 |
9 | // 输出:
10 | // ABCDE
11 | if (levels as NSString).contains("BC") {
12 | print("包含字符串")
13 | }
14 |
15 | levels.contains("")
16 |
17 |
18 | // 输出:
19 | // 包含字符串
20 |
21 |
22 | let nsRange = NSMakeRange(1, 4)
23 | // 编译错误
24 | // Cannot convert value of type `NSRanve` to expected argument type 'Range'
25 | //levels.replacingCharacters(in: nsRange, with: "AAAA")
26 |
27 | let indexPositionOne = levels.characters.index(levels.startIndex, offsetBy: 1)
28 | let swiftRange = indexPositionOne ..< levels.characters.index(levels.startIndex, offsetBy: 5)
29 | levels.replacingCharacters(in: swiftRange, with: "AAAA")
30 | // 输出:
31 | // AAAAA
32 |
33 | (levels as NSString).replacingCharacters(in: nsRange, with: "AAAA")
34 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/struct-mutating.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | /* Wrong code
5 | struct User {
6 | var age : Int
7 | var weight : Int
8 | var height : Int
9 |
10 | func gainWeight(newWeight: Int) {
11 | weight += newWeight
12 | }
13 | }
14 | */
15 |
16 | struct User {
17 | var age : Int
18 | var weight : Int
19 | var height : Int
20 |
21 | mutating func gainWeight(newWeight: Int) {
22 | weight += newWeight
23 | }
24 | }
25 |
26 | var u = User(age: 1, weight: 1, height: 1)
27 | u.gainWeight(newWeight: 2)
28 | u
29 |
30 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/struct-mutating.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/subscript.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | var arr = [1,2,3]
5 | arr[2] // 3
6 | arr[2] = 4 // arr = [1,2,4]
7 |
8 | var dic = ["cat":"meow", "goat":"mie"]
9 | dic["cat"] // {Some "meow"}
10 | dic["cat"] = "miao" // dic = ["cat":"miao", "goat":"mie"]
11 |
12 | extension Array {
13 | subscript(input: [Int]) -> ArraySlice {
14 | get {
15 | var result = ArraySlice()
16 | for i in input {
17 | assert(i < self.count, "Index out of range")
18 | result.append(self[i])
19 | }
20 | return result
21 | }
22 |
23 | set {
24 | for (index,i) in input.enumerated() {
25 | assert(i < self.count, "Index out of range")
26 | self[i] = newValue[index]
27 | }
28 | }
29 | }
30 | }
31 |
32 | arr = [1,2,3,4,5]
33 | arr[[0,2,3]] //[1,3,4]
34 | arr[[0,2,3]] = [-1,-3,-4]
35 | arr //[-1,2,-3,-4,5]
36 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/subscript.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/tail-recursion.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func sum(_ n: UInt) -> UInt {
5 | if n == 0 {
6 | return 0
7 | }
8 | return n + sum(n - 1)
9 | }
10 |
11 | sum(4)
12 | sum(100)
13 |
14 |
15 | func tailSum(_ n: UInt) -> UInt {
16 | func sumInternal(_ n: UInt, current: UInt) -> UInt {
17 | if n == 0 {
18 | return current
19 | } else {
20 | return sumInternal(n - 1, current: current + n)
21 | }
22 | }
23 |
24 | return sumInternal(n, current: 0)
25 | }
26 |
27 | // 两者在 Playground 中都会崩溃。
28 | // 请在实际项目中的 Release build 下尝试
29 | //sum(1000000)
30 | //tailSum(1000000)
31 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/tail-recursion.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/toll-free.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import AudioToolbox
4 |
5 | let fileURL = NSURL(string: "SomeURL")
6 | var theSoundID: SystemSoundID = 0
7 | AudioServicesCreateSystemSoundID(fileURL!, &theSoundID)
8 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/toll-free.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/tuple.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | func swapMe1( a: inout T, b: inout T) {
5 | let temp = a
6 | a = b
7 | b = temp
8 | }
9 |
10 | func swapMe2( a: inout T, b: inout T) {
11 | (a,b) = (b,a)
12 | }
13 |
14 | var a = 1
15 | var b = 2
16 |
17 | (a, b)
18 | swapMe1(a: &a, b: &b)
19 | (a, b)
20 |
21 |
22 | swapMe2(a: &a, b: &b)
23 | (a, b)
24 |
25 | let rect = CGRect(x: 0, y: 0, width: 100, height: 100)
26 |
27 | let (small, large) = rect.divided(atDistance: 20, from: .minXEdge)
28 |
29 | small
30 | large
31 |
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/tuple.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/type-encode.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | let int: Int = 0
5 | let float: Float = 0.0
6 | let double: Double = 0.0
7 |
8 | let intNumber: NSNumber = int as NSNumber
9 | let floatNumber: NSNumber = float as NSNumber
10 | let doubleNumber: NSNumber = double as NSNumber
11 |
12 | String(validatingUTF8: intNumber.objCType)
13 | String(validatingUTF8: floatNumber.objCType)
14 | String(validatingUTF8: doubleNumber.objCType)
15 |
16 | // 结果分别为:
17 | // {Some "q"}
18 | // {Some "f"}
19 | // {Some "d"}
20 | // 注意,fromCString 返回的是 `String?`
21 |
22 |
23 |
24 |
25 | let p = NSValue(cgPoint: CGPoint(x: 3, y: 3))
26 | String(validatingUTF8: p.objCType)
27 | // {Some "{CGPoint=dd}"}
28 |
29 | let t = NSValue(cgAffineTransform: .identity)
30 | String(validatingUTF8: t.objCType)
31 | // {Some "{CGAffineTransform=dddddd}"}
32 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/type-encode.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/typealias.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | typealias Location = CGPoint
5 | typealias Distance = Double
6 |
7 | func distance(from location: Location,
8 | to anotherLocation: Location) -> Distance {
9 | let dx = Distance(location.x - anotherLocation.x)
10 | let dy = Distance(location.y - anotherLocation.y)
11 | return sqrt(dx * dx + dy * dy)
12 | }
13 |
14 | let origin: Location = Location(x: 0, y: 0)
15 | let point: Location = Location(x: 1, y: 1)
16 |
17 | let d = distance(from: origin, to: point)
18 |
19 | class Person {}
20 |
21 | typealias WorkId = String
22 | typealias Worker = Person
23 |
24 | //class Person {}
25 |
26 | typealias WorkerGeneric = Person
27 |
28 | let w1 = Worker()
29 | let w2 = WorkerGeneric()
30 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/unsafe.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func method(_ num: UnsafePointer) {
5 | print(num.pointee)
6 | }
7 |
8 | // Swift
9 | var a: CInt = 123
10 | method(&a) // 输出 123
11 |
12 | let arr = NSArray(object: "meow")
13 | let str = unsafeBitCast(CFArrayGetValueAtIndex(arr, 0), to: CFString.self)
14 | // str = "meow"
15 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/unsafe.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/use-self.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | protocol Copyable {
5 | func copy() -> Self
6 | }
7 |
8 | class MyClass: Copyable {
9 |
10 | var num = 1
11 |
12 | func copy() -> Self {
13 | let result = type(of: self).init()
14 | result.num = num
15 | return result
16 | }
17 |
18 | required init() {
19 |
20 | }
21 | }
22 |
23 | let object = MyClass()
24 | object.num = 100
25 |
26 | let newObject = object.copy()
27 | object.num = 1
28 |
29 | print(object.num) // 1
30 | print(newObject.num) // 100
31 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/use-self.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/value-reference.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func test(_ arr: [Int]) {
5 | for i in arr {
6 | print(i)
7 | }
8 | }
9 |
10 | var a1 = [1,2,3]
11 | var b1 = a1
12 | let c1 = b1
13 | test(a1)
14 |
15 | var a2 = [1,2,3]
16 | var b2 = a2
17 | b2.append(5)
18 | // 此时 a 和 b 的内存地址不再相同
19 |
20 | class MyObject {
21 | var num = 0
22 | }
23 |
24 | var myObject = MyObject()
25 | var a3 = [myObject]
26 | var b3 = a3
27 |
28 | b3.append(myObject)
29 |
30 | myObject.num = 100
31 | print(b3[0].num) //100
32 | print(b3[1].num) //100
33 |
34 | // myObject 的改动同时影响了 b3[0] 和 b3[1]
35 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/variadic.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | func sum(input: Int...) -> Int {
5 | return input.reduce(0, +)
6 | }
7 |
8 | print(sum(input: 1,2,3,4,5))
9 | // 输出:15
10 |
11 | func myFunc(numbers: Int..., string: String) {
12 | numbers.forEach {
13 | for i in 0..<$0 {
14 | print("\(i + 1): \(string)")
15 | }
16 | }
17 | }
18 |
19 | myFunc(numbers: 1, 2, 3, string: "hello")
20 |
21 |
22 |
23 | let name = "Tom"
24 | let date = NSDate()
25 | let string = NSString(format: "Hello %@. Date: %@", name, date)
26 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/variadic.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/where.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | let name = ["王小二","张三","李四","王二小"]
5 |
6 | name.forEach {
7 | switch $0 {
8 | case let x where x.hasPrefix("王"):
9 | print("\(x)是笔者本家")
10 | default:
11 | print("你好,\($0)")
12 | }
13 | }
14 |
15 | // 输出:
16 | // 王小二是笔者本家
17 | // 你好,张三
18 | // 你好,李四
19 | // 王二小是笔者本家
20 |
21 | let num: [Int?] = [48, 99, nil]
22 |
23 | let n = num.flatMap {$0}
24 | for score in n where score > 60 {
25 | print("及格啦 - \(score)")
26 | }
27 | // 输出:
28 | // 及格啦 - Optional(99)
29 |
30 | num.forEach {
31 | if let score = $0, score > 60 {
32 | print("及格啦 - \(score)")
33 | } else {
34 | print(":(")
35 | }
36 | }
37 | // 输出:
38 | // :(
39 | // 及格啦 - 99
40 | // :(
41 |
42 | let sortableArray: [Int] = [3,1,2,4,5]
43 | let unsortableArray: [Any?] = ["Hello", 4, nil]
44 |
45 | sortableArray.sorted()
46 |
47 | //unsortableArray.sorted()
48 |
49 |
--------------------------------------------------------------------------------
/Swifter.playground/Pages/where.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Swifter.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/Swifter.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Swifter.playground/playground.xcworkspace/xcshareddata/Swifter.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "7502F96F5C4E53E5E4D8F6D0CE6682F7FD5510AE",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "7502F96F5C4E53E5E4D8F6D0CE6682F7FD5510AE" : 0,
8 | "C06821B1F3517FF3FE504C9E5AB8525DE79DEFEF" : 0
9 | },
10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "73A4433D-12C5-4FD5-982D-850CC97BED98",
11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 | "7502F96F5C4E53E5E4D8F6D0CE6682F7FD5510AE" : "playground\/",
13 | "C06821B1F3517FF3FE504C9E5AB8525DE79DEFEF" : ""
14 | },
15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "Swifter",
16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Swifter.playground",
18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19 | {
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:swifter-tips\/Playground.git",
21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "7502F96F5C4E53E5E4D8F6D0CE6682F7FD5510AE"
23 | },
24 | {
25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "gitlab.com:onevcat\/swifter.git",
26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "C06821B1F3517FF3FE504C9E5AB8525DE79DEFEF"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/Swifter.playground/playground.xcworkspace/xcuserdata/JP20028.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swifter-tips/Playground/3d841ad3f9cf530dc925e65ba1f52c003b8b572d/Swifter.playground/playground.xcworkspace/xcuserdata/JP20028.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Swifter.playground/playground.xcworkspace/xcuserdata/JP20028.xcuserdatad/userinterfacestate (Wei Wang の競合コピー 2016-09-07).xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swifter-tips/Playground/3d841ad3f9cf530dc925e65ba1f52c003b8b572d/Swifter.playground/playground.xcworkspace/xcuserdata/JP20028.xcuserdatad/userinterfacestate (Wei Wang の競合コピー 2016-09-07).xcuserstate
--------------------------------------------------------------------------------
/Swifter.playground/playground.xcworkspace/xcuserdata/onevcat.xcuserdatad/UserInterfaceState (Wei Wang の競合コピー 2016-09-07).xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swifter-tips/Playground/3d841ad3f9cf530dc925e65ba1f52c003b8b572d/Swifter.playground/playground.xcworkspace/xcuserdata/onevcat.xcuserdatad/UserInterfaceState (Wei Wang の競合コピー 2016-09-07).xcuserstate
--------------------------------------------------------------------------------
/Swifter.playground/playground.xcworkspace/xcuserdata/onevcat.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swifter-tips/Playground/3d841ad3f9cf530dc925e65ba1f52c003b8b572d/Swifter.playground/playground.xcworkspace/xcuserdata/onevcat.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------