美文网首页
Swift十九(OC 到 Swift 2)

Swift十九(OC 到 Swift 2)

作者: 看谷秀 | 来源:发表于2022-07-22 17:22 被阅读0次

    目录

    1. 是否继承 NSObject 内存分析
    2. optional 可选协议
    3. dynamic 关键字
    4. Swift 代码使用 OC 的 KVC/ KVO
    5. 关联对象(Associated Object)
    6. 资源管理名 image & font 封装策略
    一: 是否继承 NSObject 内存分析
    class Person {
        var age = 10
        var weight: Int = 0
    }
    

    内存结构Person对象占用32位,
    最前8个字节指向元类, 然后8个字节引用计数相关, 在后8个字节 age , 最后8个字节 weight

    class Person: NSObject {
        var age = 10
        var weight: Int = 0
    }
    

    内存结构 Person 对象占用32位, 最前8个字节存放isa指针, 然后8个字节 age , 最后8个字节 weight , 最后8个字节内存对齐

    二: 可选协议

    1 这些协议只能被类遵守

    protocol Runnable1: AnyObject {}
    protocol Runnable2: class {}  // 这个过期了 AnyObject代替
    @objc protocol Runnable3 {} // 除了需要被类swift类遵守, 还将暴露给外部oc类调用
    

    2 可选协议

    class SwiftTestController: FTBaseViewController, xxprotocal {
    }
    @objc protocol xxprotocal {
        @objc optional func test() 
        // 加上 @objc optional  为可选协议, 遵守类可以不实现方法
    }
    

    3 或是通过扩展实现协议方法, 打到遵守协议类, 可以不实现协议方法效果

    extension xxprotocal {
        func test() {
        }
    }
    
    三: dynamic 关键字

    被 @objc dynamic 修饰的内容会具有动态性,比如调用方法会走runtime那一套流程

    四: Swift 代码使用 OC 的 KVC/ KVO

    1. Swift 代码调用 OC 的 KVC/ KVO

    以方法方式调用 KVO


    以Block 方式调用 KVO

    2. 补充: swift的属性监听器
    class Person {
    var name : String? {
        willSet {  // 属性即将改变时进行监听
              print("willSet--name----\(name)")
              print("willSet--newValue----\(newValue)")
         }
         didSet {  // 属性已经改变时进行监听
              print("didSet--name----\(name)")
              print("didSet--oldValue----\(oldValue)")
         }
    }
    }
    let p = Person()
    p.name = "why"
    p.name = "yz"
    
    ** 打印结果**
    willSet--name----nil
    willSet--newValue----Optional("why")
    didSet--name----Optional("why")
    didSet--oldValue----nil
    
    willSet--name----Optional("why")
    willSet--newValue----Optional("yz")
    didSet--name----Optional("yz")
    didSet--oldValue----Optional("why")
    
    五: 关联对象(Associated Object)

    在Swift中,class依然可以使用关联对象
    默认情况,extension不可以增加存储属性
    借助关联对象,可以实现类似extension为class增加存储属性的效果

    class Person { }
    extension Person {
    // 定义全局变量, 只要为了用地址值, Void占一个内存
    private static var AGE_KEY: Void?
    var age: Int {
        get {
               (objc_getAssociatedObject(self, &Self.AGE_KEY) as? Int) ?? 0
        }
        set {
        objc_setAssociatedObject(self, &Self.AGE_KEY, // 关联地址值
        newValue, // 传进来的变量
        .OBJC_ASSOCIATION_ASSIGN)  // 存储策略
        } 
    }
    }
    
    var p = Person()
    print(p.age) // 0
    p.age = 10
    print(p.age) // 10
    
    六: 资源管理名

    1 图片& 字体封装策略


    2 其他策略

    更多优秀的思路参考
    phttps://github.com/mac-cain13/R.swift
    phttps://github.com/SwiftGen/SwiftGen
    七: 多线程
      1. DispatchQueue
    // 异步并发队列
    let queue1 = DispatchQueue(label: "com.Miss.queue", qos: .default, attributes: .concurrent)
           queue1.async(group: group) {
                Thread.sleep(forTimeInterval: 3)
                print("翻翻书")
                
            }
                    
    let queue2 = DispatchQueue(label: "com.Miss.queue", qos: .default, attributes: .concurrent)
            queue2.async(group: group) {
                print("画画画")
    //            Thread.sleep(forTimeInterval: 1)
            }
                    
    let queue3 = DispatchQueue(label: "com.Miss.queue", qos: .default, attributes: .concurrent)
            queue3.async(group: group) {
                print("看看景")
                Thread.sleep(forTimeInterval: 2)
            }
                    
    group.notify(queue: DispatchQueue.main) {
                print("收拾下")
            }
         /** 
        画画画
        看看景
        翻翻书
        收拾下
         **/
    

    多线程 -- 补充DispatchQueue & DispatchWorkItem

      1. 延迟执行 asyncAfter
    let item  = DispatchWorkItem {
        print("来来来\(Thread.current)")
    }
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3, execute: item)
    DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 3) {
         print("来来来\(Thread.current)") 
    }
    // 来来来<_NSMainThread: 0x6000035c86c0>{number = 1, name = main}
    // 来来来<NSThread: 0x600003549b40>{number = 7, name = (null)}
    
      1. 初始化一次 单例可以用
        dispatch_once 在Swift中已被废弃
        可以创建静态全局变量/ 变量 实现 static
        默认自带 lazy + dispatch_once 效果
    fileprivate let initTask2: Void = { // 静态全局变量
       print("initTask2---------")
    }()
    class ViewController: UIViewController {
       static let initTask1: Void = { // 静态局部变量
       print("initTask1---------")
    }()
    override func viewDidLoad() {
       super.viewDidLoad()
       let _ = Self.initTask1 // 初始一次
       let _ = initTask2 // 初始画一次
    }
    
      1. 多线程 加锁
        4.1 信号量加锁
    // 封装一个缓存库
    class Cache {
      private static var data = [String: Any]()
      private static var lock = DispatchSemaphore(value: 2) // 最多两条线程可以访问
    
      static func set(_ key: String, _ value: Any) {
      lock.wait()
      defer { lock.signal() } // defer: 方法退出前执行
      data[key] = value
      }
    }
    

    4.2 Foundation NSLock

    private static var lock = NSLock()
    static func set(_ key: String, _ value: Any) {
      lock.lock()
      defer {lock.unLock()}
    }
    

    4.3 递归锁
    方法中包含递归调用时候使用

    rivate static var lock = NSRecursiveLock()
    static func set(_ key: String, _ value: Any) {
      lock.lock()
      defer { lock.unlock()}
    }
    
    八: Array 常用Api
      1. 遍历数组
    let array = [1,2,3,4]
    
    //  func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
    // 返回数组, 遍历数组, 通过item返回每个元素, 表达式返回每个新元素, 同时生成一个新数组
    
    let array1 = array.map { (item: Int) -> Int  in
         item * 2   // { $0 * 2 }
    }
    print(array1) // [2, 4, 6, 8]
    
    let array11 = array.map { item in 
         "\(item)"
    }
    print(array11) // ["1", "2", "3", "4"]
    
      1. 过滤数组
    //  func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> [Element]
    //  返回数组, 通过表达式返回Bool值, 过滤掉返回false的值
    
    let array2 = array.filter { item in
         item / 2 == 0   // { $0 / 2 }
    }
    print(array2) // [1]
    
      1. 遍历带参数保存结果
    // func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
    // 返回值, 初始值, 闭包返回的Result值三者相同, 
    // 表达式计算结果通过 partialResult 保存
    let array3 = array.reduce(1) { (partialResult, Element) -> Int in
        return partialResult + Element // { $0 + $1 }
    }
    print(array3) // 10
    
      1. 相关
    // 遍历 字符串数组 转Int数组
    let arr = ["123", "test", "jack", "-30"]
    var arr2 = arr.map { Int($0) }
    print(arr2) // [Optional(123), nil, nil, Optional(-30)]
    // 缩进数组
    var arr3 = arr.compactMap { Int($0) }
    print(arr3) // [123, -30]
    
    var arr = [1, 2, 3]
    // [[1], [2, 2], [3, 3, 3]]
    var arr2 = arr.map { Array.init(repeating: $0, count: $0) }
    // [1, 2, 2, 3, 3, 3]
    var arr3 = arr.flatMap { Array.init(repeating: $0, count: $
    
    // 数组遵守了equalable协议
    let array =  [1] + [1,2]
    print(array) // [1, 1, 2]
    
    九: Optional的map和flatMap
      1. 可选项.map, 可选项 .flatMap
    var num1: Int? = 10
    var num2 = num1.map { (num) -> Int in
        num * 2
    }   // Optional(20)
    var num3: Int? = nil 
    var num4 = num3.map { $0 * 2 } // nil
    // 有值返回可选类型, 否则返回nil
    
    var num1: Int? = 10
    var num2 = num1.map { Optional.some($0 * 2) } // Optional(Optional(20))
    var num3 = num1.flatMap { Optional.some($0 * 2) } // Optional(20)
    // flatMap发现是可选类型, 就不在加可选了
    
    var num1: Int? = 10
    var num2 = (num1 != nil) ? (num1! + 10) : nil
    var num3 = num1.map { $0 + 10 }
    // 省去了判断可选是否为nil 的操作
    
    var fmt = DateFormatter()
    fmt.dateFormat = "yyyy-MM-dd"
    var str: String? = "2011-09-10"
    // old写法
    var date1 = str != nil ? fmt.date(from: str!) : nil
    // new
    var date3 = str.flatMap { string in
        return fmt.date(from: string)
    }
    var date2 = str.flatMap(fmt.date) // 参数是闭包 fmt.date是函数, so...
    // 日期格式设置可选时间
    
    var score: Int? = 98
    // old
    var str1 = score != nil ? "socre is \(score!)" : "No score"
    // new
    var str2 = score.map { "score is \($0)" } ?? "No score"
    

    相关文章

      网友评论

          本文标题:Swift十九(OC 到 Swift 2)

          本文链接:https://www.haomeiwen.com/subject/taiuirtx.html