使用 Swift 3 #keyPath 引用 UIView 子类 .center

Referencing UIView subclass .center with Swift 3 #keyPath

在我的应用程序的视图控制器中,我通过观察其 center 属性 的键值对视图定位的更改做出反应,如下所示:

class CoordinatingViewController: UIViewController {

    @IBOutlet weak var cardContainerView: CardView!

    override func viewDidLoad() {
         super.viewDidLoad()
         addObserver(self, forKeyPath: "cardContainerView.center", options: [.new], context: nil)
    }
}

这目前工作得很好,但由于该关键路径是一个字符串,因此编译器无法对其进行检查。为了缓解这种情况,我想使用 Swift 3 的 #keyPath() 语法,它采用编译器检查的密钥路径和 returns 正确的对应字符串。但是,当我更改该行以像这样使用它时:

addObserver(self, forKeyPath: #keyPath(cardContainerView.center), options: [.new], context: nil)

编译器给我 2 个错误:

  1. Type 'CardView!' has no member 'center'
  2. Cannot refer to type member 'center' within instance of type 'CardView!'

我不明白为什么我会收到这些错误,因为 centerUIView 的文档 属性,CardView 直接继承自我可以在 #keyPath() 语句之外读取和写入。此外,当我直接将键路径作为字符串传递时,一切似乎都正常,就像在我的第一个示例中一样,这使得这更加混乱。我怎样才能让编译器为我检查那个关键路径?

似乎 Swift 对 weak 修饰符不满意。删除它,代码将编译。从 this, we can see that outlets are recommended to be strong, unless you actually have a retain cycle. See my answer 了解如何查找保留周期。

在 Swift 4 中,您将能够使用新的 \ 键路径语法执行此操作:

// no problems with "weak"!
let observation = observe(\.cardContainerView.center) { (object, change) in
    ...
}