Swift十九(OC 到 Swift 2)

2022-07-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
七: 多线程
// 异步并发队列
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

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)}
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 // 初始画一次
}
// 封装一个缓存库
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
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"]
//  func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> [Element]
//  返回数组, 通过表达式返回Bool值, 过滤掉返回false的值

let array2 = array.filter { item in
     item / 2 == 0   // { $0 / 2 }
}
print(array2) // [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
// 遍历 字符串数组 转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
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"
上一篇 下一篇

猜你喜欢

热点阅读