我有很多类似的课程:
class Dog {
var name = ""
}
class Cat {
var name = ""
}
还有一个在方法内部带有闭包的类:
class Reader {
func read(_ block: (() -> Void)) {
block()
}
}
在更改闭包内第一个对象的属性后:
let reader = Reader()
reader.read {
dog.name = "Bob"
cat.name = "Tom"
}
我需要在 dog 和 cat 对象内部获取对 reader 的引用。 该怎么做?
PS: 可以从具有某些附加功能的某些父类继承Dog和Cat类
更新1:
我需要得到类似的东西:
class Reader {
func doSomething(_ value: String) {
print(value)
}
func read(_ block: (() -> Void)) {
block()
}
}
class Dog {
var name = "" {
didSet {
reader?.doSomething(name) //!!!!! Main needed feature
// reader object with it unique name will be init later
}
}
}
当我在 read 闭包内更改Dog类的 name 属性时:
let reader = Reader()
reader.read {
dog.name = "Bob"
}
reader?.doSomething(name)必须执行。
答案 0 :(得分:0)
嗯,我认为最简单的方法是将捕获的对象传递给读取函数并使用KVO来捕获更新的值:
class ReadableObject: NSObject {
weak var reader: Reader?
}
class Reader: NSObject {
private var observerContext = 0
func doSomething(with value: Any?, of property: String) {
print("value of \(property) modified to: '\(value ?? "")'")
}
func read(capturedObjects:[ReadableObject], block: (() -> Void)) {
capturedObjects.forEach({ object in
object.reader = self
let properties = Mirror(reflecting: object).children.compactMap { $0.label }
properties.forEach({ (property) in
object.addObserver(self, forKeyPath: property, options: [.new], context: &observerContext)
})
})
block()
capturedObjects.forEach({$0.reader = nil})
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard context == &observerContext, let kp = keyPath, let obj = object as? ReadableObject else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
let value = obj.value(forKeyPath: kp)
let className = NSStringFromClass(type(of: obj)).components(separatedBy: ".").last ?? ""
obj.reader?.doSomething(with: value, of: "\(className).\(kp)")
}
}
然后从ReadableObject
继承您的类,并将所有可读属性标记为“ @obj dynamic”(以使其可观察)。
class Dog: ReadableObject {
@objc dynamic var name: String = ""
}
class Cat: ReadableObject {
@objc dynamic var name: String = ""
}
用法:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let reader = Reader()
let dog = Dog()
let cat = Cat()
reader.read(capturedObjects: [dog, cat]) {
dog.name = "Bob"
cat.name = "Tom"
}
}
}
控制台日志:
Dog.name的值修改为:'Bob'
Cat.name的值修改为:“ Tom”
========================
编辑
如果您不想使用KVO,则可以选择使用didSet
块:
class Dog: ReadableObject {
var name: String = "" {
didSet {
if let reader = reader { //If reader is not nil, then the property was modified inside "read" block
reader?.doSomething(with: name, of: "Dog.name")
}
}
}
}
class Cat: ReadableObject {
var name: String = "" {
didSet {
if let reader = reader {
reader?.doSomething(with: name, of: "Cat.name")
}
}
}
}