Swift高级用法

---
 持续更新
⭐️重载 +*:
 let result = v1 +* v2

    precedencegroup DotProductPrecedence {
        associativity: none
        higherThan: MultiplicationPrecedence
    }
    infix operator +*: DotProductPre
---
### ⭐️inout:
    方法内部直接修改输入的值,这时候我们可以使用 inout
    
    func incrementor(variable: inout Int) {
        variable += 1
    }
    
    var luckyNumber = 7
    incrementor(variable: &luckyNumber)
    print(luckyNumber)
    // luckyNumber = 8
---
### ⭐️ExpressibleByBooleanLiteral 自定义Bool

    enum MyBool: Int {
        case myTrue,
        myFalse
    }
    
    let myTrue: MyBool = true
    let myFalse: MyBool = false

---
### ⭐️字面量 ExpressibleByStringLiteral
 

    class Person {
        let name: String
        init(name value: String) {
        self.name = value
     }
    }
    
    class Person: ExpressibleByStringLiteral {
        let name: String
        init(name value: String) {
        self.name = value }
        required init(stringLiteral value: String) {
            self.name = value
        }
        required init(extendedGraphemeClusterLiteral value: String)         {
            self.name = value
        }
        required init(unicodeScalarLiteral value: String)         {
        self.name = value
        }
    }

    class Person: ExpressibleByStringLiteral {
        let name: String
        init(name value: String) {
        self.name = value
    }
    
    required convenience init(stringLiteral value: String)         {
        self.init(name: value)
    }
    required convenience init(extendedGraphemeClusterLiteral value: String) {
        self.init(name: value)
    }
    required convenience init(unicodeScalarLiteral value: String)     {
        self.init(name: value)
    }
    }
    let p: Person = "xiaoMing"
    print(p.name)
    // 输出:// xiaoMing

---
### ⭐️下标  ExpressibleByStringLiteral


    
    Array
    {
        subscript(input: [Int]) -> ArraySlice {
        get {
             var result = ArraySlice() for i in input {
            assert(i < self.count, "Index out of range")
            result.append(self[i]) }
            return result
             }
        set {
            for (index,i) in input.enumerated() {
                   
                assert(i < self.count, "Index out of range")
                self[i] = newValue[index] }
          
            }
        }
    }
    使用
    var arr = [1,2,3,4,5]
    arr[[0,2,3]]
    //[1,3,4]
    arr[[0,2,3]] = [-1,-3,-4]
    arr
    //[-1,2,-3,-4,5]

---
### ⭐️命名空间
    // MyFramework.swift
    // 这个文件存在于 MyFramework.framework 中
    public class     MyClass {
        public class func hello()
        {
            print("hello from   framework")
        }
    }
    // MyApp.swift    // 这个文件存在于 app 的主 target 中
    class MyClass {
        class func hello()
        {
            print("hello from app")
        }
    }
    使用
        
    MyClass.hello()
    // hello from app
    MyFramework.MyClass.hello()
    // hello from framework
    因为是在 app 的 target 中调用的,所以第一个 MyClass 会直接使用 app 中的版本
    第二个调用我 们指定了 MyFramework 中的版本。


---
### ⭐️初始化方法顺序
    1. 设置子类自己需要初始化的参数
    2. 调用父类的相应的初始化方法,super.init()
    3. 对父类中的需要改变的成员进行设定
    super.init() 也是可以不用写的 (但是实际上还是调用的,只不过是为了简便 Swift 帮我们 完成了)
    Swift 的初始化方法需要保证类型的所有属性都被初始化

---
### ⭐️Designated,Convenience 和 Required
    与 designated 初始化方法对应的是在 init 前加上 convenience 关键字的初始化方法。
    这类方法 是 Swift 初始化方法中的 “二等公⺠”,只作为补充和提供使用上的方便。
    所有的 convenience 初始 化方法都必须调用同一个类中的 designated 初始化完成设置,
    另外 convenience 的初始化方法是 不能被子类重写或者是从子类中以 super 的方式被调用的。
 
     在 Swift 中 let 声明的值是常量,无法被写入赋值,这对于构建 线程安全 的API十分有用。
     而因为 Swift 的 init 只可能被调用一次,因此在 init 中我们可以为常量进行赋值,而不 会引起任何线程安全的问题。
    
    class ClassA {
        let numA: Int
        init(num: Int)
        {
            numA = num
        }
    convenience init(bigNum: Bool)
        {
            self.init(num: bigNum ? 10000 : 1)
        }
    }
    class ClassB: ClassA
    {
        let numB: Int
        override init(num: Int)
        {
            numB = num + 1
            super.init(num: num)
        }
    }
    let anObj = ClassB(bigNum: true)
    //anObj.numA = 10000, anObj.numB = 10001

---
### ⭐️CustomStringConvertible
    let mixed: [CustomStringConvertible] = [1, "two", 3]
    for obj in mixed {
        print(obj.description)
    }

---
### ⭐️属性观察
    class A {
       var number :Int {
    get
    {
        print("get")
        return 1
    }
    set {
            print("set")}
        }
    }
    class B: A {
        override var number: Int
        {
        willSet {
            print("willSet")
            }
        didSet {
            print("didSet")
            }
        }
    }



    let b = B() b.number = 0
    // 输出
    // get
    // willSet
    // set
    // didSet
    
    set 和对应的属性观察的调用都在我们的预想之中。
    这里要注意的是 get 首先被调用了一次。 这是因为我们实现了 didSet ,
    didSet 中会用到 oldValue ,
    而这个值需要在整个 set 动作之前进 行获取并存储待用,否则将无法确保正确性。
    如果我们不实现 didSet 的话,这次 get 操作也将 不存在。

---
### ⭐️子类继承和修改是一件危险的事情
    如果子类重写了父类方法,是没有办法强制子类方法 一定去调用相同的父类方法的。在 Objective-C 的时候我们可以通过指定
    __attribute__((objc_requires_super)) 这样的属性来让编译器在子类没有调用父类方法时抛出警告。

    class Parent {
        final func method() {
            print("开始配置")
            // ..必要的代码
             methodImpl()
            // ..必要的代码
            print("结束配置")
        }
        func methodImpl() {
            fatalError("子类必须实现这个方法") // 或者也可以给出默认实现
        }
    }
    class Child: Parent {
        override func methodImpl()
        {
                //..子类的业务逻辑
        }
    }
    这样,无论如何我们如何使用 method ,都可以保证需要的代码一定被运行过,而同时又给了子类 继承和重写自定义具体实现的机会。


---
### ⭐️lazy 修饰符和 lazy 方法
延时加载或者说延时初始化是很常用的优化方法,在构建和生成新的对象的时候,内存分配会在 运行时耗费不少时间,如果有一些对象的属性和内容非常复杂的话,这个时间更是不可忽略。另 外,有些情况下我们并不会立即用到一个对象的所有属性,而默认情况下初始化时,那些在特定 环境下不被使用的存储属性,也一样要被初始化和赋值,也是一种浪费。

    在使用 lazy 作为属性修饰符时,只能声明属性是变量。
    要显式地指定属性类型
    并使用一个可以对这个属性进行赋值的语句来在首次访问属性时运行
    let data = 1...3    let result = data.map {
        (i: Int) -> Int in
            print("正在处理 \(i)")
        return i * 2
    }
    print("准备访问结果")
    for i in result{
        print("操作后结果为 \(i)") }
        print("操作完毕")
        // 正在处理 1
        // 正在处理 2
        // 正在处理 3
        // 准备访问结果
        // 操作后结果为 2
        // 操作后结果为 4
        // 操作后结果为 6
        // 操作完毕
    
    let data = 1...3    let result = data.lazy.map {
        (i: Int) -> Int in
        print("正在处理 \(i)")
        return i * 2
    }
    print("准备访问结果")
    for i in result {
        print("操作后结果为 \(i)")
    }
    print("操作完毕")
    // 准备访问结果
    // 正在处理 1
    // 操作后结果为 2
    // 正在处理 2
    // 操作后结果为 4
    // 正在处理 3
    // 操作后结果为 6
    // 操作完毕

---
### ⭐️Reflection 和 Mirror
    struct Person {
        let name: String
        let age: Int
    }
    let xiaoMing = Person(name: "XiaoMing", age: 16)
    let r = Mirror(reflecting: xiaoMing)
    // r 是     MirrorType
    print("xiaoMing 是 \(r.displayStyle!)")
    print("属性个数:\(r.children.count)")
    for child in r.children {
        print("属性名:\(String(describing: child.label)),值:\(child.value)")
    }
    // 输出:
    // xiaoMing 是 Struct
    // 属性个数:2
    // 属性名:name,值:XiaoMing // 属性名:age,值:16



    func valueFrom(_ object: Any, key: String) -> Any?     {
        let mirror = Mirror(reflecting: object)
        for child in mirror.children {
            let (targetKey, targetMirror) = (child.label,child.value)
            if key == targetKey
            {
                return targetMirror
            }
        }
        return nil
    }
    // 接上面的 xiaoMing
    if let name = valueFrom(xiaoMing, key: "name") as?     String {
        print("通过 key 得到值: \(name)")
    }
    // 输出:
    // 通过 key 得到值: XiaoMing


---
### ⭐️where 和模式匹配
    let name = ["王小二","张三","李四","王二小"]
    name.forEach {
        switch $0 {
            case let x where x.hasPrefix("王"):
            print("\(x)是笔者本家")
            default: print("你好,\($0)")
        }
    }
    // 输出:
    // 王小二是笔者本家 // 你好,张三
    // 你好,李四
    // 王二小是笔者本家


    let num: [Int?] = [48, 99, nil]
    let n =  num.flatMap {$0}
    for score in n where score > 60
    {
        print("及格啦 - \(score)")
    }
    // 输出:
    // 及格啦 - Optional(99)

---
### ⭐️Lock
    func myMethod(anObj: AnyObject!) {
        objc_sync_enter(anObj)
         // 在 enter 和 exit 之间持有 anObj 锁
         objc_sync_exit(anObj)
    }
    
    更进一步,如果我们喜欢以前的那种形式,
    甚至可以写一个全局的方法,并接受一个闭包,
    来将 objc_sync_enter 和 objc_sync_exit 封装起来:
    
    func synchronized(_ lock: AnyObject, closure: () -> ())
    {
        objc_sync_enter(lock)
        closure()
        objc_sync_exit(lock)
    }

---
### ⭐️fatalError
    @noreturn func fatalError(
        @autoclosure message: () -> String = default, file:
        StaticString = default,
        line: UInt = default)
    

    class MyClass {
        func methodMustBeImplementedInSubclass() {
        fatalError("这个方法必须在子类中被重写") }
    }
    class YourClass: MyClass {
        override func methodMustBeImplementedInSubclass()
        {
            print("YourClass 实现了该方法") }
        }
        class TheirClass: MyClass {
            func someOtherMethod() {
        }
    }
    YourClass().methodMustBeImplementedInSubclass()
    // YourClass 实现了该方法
    TheirClass().methodMustBeImplementedInSubclass()
    // 这个方法必须在子类中被重写

---
### ⭐️属性访问控制
    private 让代码只能在当前作用域或者同一文件中同一类型的作用域中被使用,    fileprivate
    表示
    代码可以在当前文件中被访问,而不做类型限定。例如,以下代码是合法的:
    
    class Foo {
            private privateBar = Bar()
            fileprivate filePrivateBar = Bar()
        }
    class Baz {
        func baz() {
                print(Foo().filePrivateBar)
            }
        }
    extension Foo {
        func fooExtension() {
             print(privateBar)
      }
    }
---
### ⭐️defer
defer block 里的代码会在函数 return 之前执行,无论函数是从哪个分支 return 的,还是有 throw,还是自然而然走到最后一行。

    func foo() {
        defer { print("finally") }
        do {
            throw NSError() print("impossible")
        }
     catch {
         print("handle error")
      }
     }


---
### ⭐️ swift 协议泛型associatedtype
协议 中不支持这中方式写泛型

    protocol Container{
        associatedtype ItemType
        mutating func append(_ item:ItemType)
        var count:Int{get}
        subscript(i:Int)->ItemType{get}
    }

    struct InStack: Container{
        var count: Int
            var items=[Int]()
        mutating func append(_ item: Int) {
            items.append(item)
        }
               
        subscript(i: Int) -> Int {
            return items[i]
        }
        
        typealias ItemType = Int
        
        //自定义方法
        mutating func pop()->Int{
            return items.removeLast()
        }
        
    }

---
### ⭐️  Swift中如何通过一个类的 Class 创建这个类的对象

     var clazz = ViewController.classForCoder; 如何通过 这个 clazz创建一个 ViewController的对象。
---


### ⭐️ Swift中协议的可选方法的实现判断
    if(self.delegate.responseToSelector(@selector(method)){
        [self.delegate method]
    }
---
### ⭐️ typealias与泛型

下面这样的命名都是无法通过编译的

    class Person {}  
    typealias Woker = Person  
    typealias Worker = Person  

不过如果我们在别名中也引入泛型,是可以进行对应的

    class Person {}  
    typealias Woker = Person  
    typealias Worker = Person  

---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---
### ⭐️ to be continue
---

你可能感兴趣的:(Swift高级用法)