一步步学习Swift

Swift学习之KeyPath

2023-05-18  本文已影响0人  冷武橘

一、什么是KeyPath

KeyPath:一个指定类型下的结果值的类型的路径
class KeyPath<Root, Value>

struct Student{
    var name:String = ""
   let nameKeyPath:KeyPath<Student, String> = \Student.name
}

二、KeyPath的使用

struct Student{
    var name:String = ""
}

 let s = Student(name: "张三")
  let nameKeyPath: KeyPath<Student, String> = \Student.name        
  let name = s[keyPath: nameKeyPath]     
   print(name)

代替闭包

        let s = Student(name: "张三")
        let s1 = Student(name: "李四")
        let array = [s,s1]
        let names = array.map {$0.name}

上面map闭包获取所有的名字可以用keyPath代替:

  let s = Student(name: "张三")
       let s1 = Student(name: "李四")
       
       let array = [s,s1]
       let names = array.map {$0.name}
       let namess = array.map(\.name)

类似协议封装的效果

import UIKit
struct CellConfigurator<Model> {
    let titleKeyPath: KeyPath<Model, String>
    let descKeyPath: KeyPath<Model, String>
    func configure(_ cell: UITableViewCell?, for model: Model) {
        cell?.textLabel?.text = model[keyPath: titleKeyPath]
        cell?.detailTextLabel?.text = model[keyPath: descKeyPath]
    }
}
struct Student{
    var title:String
    var desc:String
}
class ViewController: UIViewController {
  
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let s = Student(title: "111", desc:"22")
     
        let cellConfigure = CellConfigurator(titleKeyPath: \Student.title, descKeyPath: \Student.desc)
        cellConfigure.configure(UITableViewCell(), for: s)
    }
}

三、KeyPath的类型

struct Cat{
    var name:String  
}
var cat = Cat(name: "hhh")
let nameKeyPath:WritableKeyPath = \Cat.name
print(cat[keyPath: nameKeyPath])
cat[keyPath: nameKeyPath] = "aaa"
print(cat.name)
class Cat{
    var name:String = "111"  
}
var cat = Cat()
let nameKeyPath:ReferenceWritableKeyPath = \Cat.name
print(cat[keyPath: nameKeyPath])
cat[keyPath: nameKeyPath] = "aaa"
print(cat.name)

Converting to functions

class ListViewController {
    private var items = [Item]() { didSet { render() } }

    func loadItems() {
        loader.load { [weak self] items in
            self?.items = items
        }
    }
}

上面的例子,我们通常为了避免循环引用[weak self]是必不可少的,这里我们就可以通过ReferenceWritableKeyPath来更加巧妙地解决这个问题;

func setter<Object: AnyObject, Value>(for object: Object, keyPath: ReferenceWritableKeyPath<Object, Value>) -> (Value) -> Void {
    return { [weak object] value in
        object?[keyPath: keyPath] = value
    }
}

下面让我们去我们改写原来的代码

class ListViewController {
    private var items = [Item]() { didSet { render() } }

    func loadItems() {
        loader.load(then: setter(for: self, keyPath: \.items))
    }
}
上一篇 下一篇

猜你喜欢

热点阅读