检测闭包内部的对象(在Linux Swift中)

时间:2018-07-25 14:34:40

标签: swift

我有很多类似的课程:

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)必须执行。

1 个答案:

答案 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")
            }
        }
    }
}