2016-12-27 4 views
2

それはどのように私はUIViewのアルファをKVOん...この偉大な記事で技術を使用して、Swift3では、KVOはUIViewのアルファですか?

https://stackoverflow.com/a/25219216/294884

Swift3の値KVOに「簡単」ですか?

目的:小さな画面の画面を想像してください。V画面に大きな表が表示されます。各セルには小さなCVがあります。

は、私は、各CVは

(私は考えることができる唯一の本当の代替は、細胞をCADisplayLinkとアルファをポーリングすることであるV.のアルファのアニメーションの間、実際にVのアルファを、フォローしたいですV、どの種類の吸う。)そのため


理由の?これは、アルファ変更をセル間で同期させる唯一の方法です。


ロブは、レイヤーのアルファがをアニメーション化しない実際には、以下の説明と同じように。 (アニメーションの冒頭で新しい値に「即座に」設定します)実際には、プレゼンテーションレイヤーに従わなければなりません。ここでは、すべてこれはKVOの理想的なユースケースではありません

let d = CADisplayLink(target: self, selector: #selector(ThisClassName.updateAlpha)) 
d.add(to: RunLoop.current, forMode: RunLoopMode.commonModes) 

func updateAlpha() { 
    let a = leader.layer.presentation()?.value(forKey: "opacity") as! CGFloat 
    follower.alpha = a 
    } 

答えて

4

描きたい場所からそれを引っ張って、逆のプロセスの例です。 alphaを変更しているコードに行き、他のビューの必要な更新を行うことを好みます(または、より一般的に行うためにいくつかのインターフェイスを構築します; KVO以外のもの)。

アニメーションを扱う場合、alphaのKVOは、アニメーションの開始中にアニメーション中の途中での変更を観察しないでください。 (変更のこれらの種類は、一般的にCADisplayLinkなどでpresentation/presentationLayerで撮影されている。)はい、あなたはalphaプロパティを観察することができ、という

を語りました。だから、スウィフト3に、ちょうどコンテキストを定義します。その後、

private var observerContext = 0 

、観察者追加:

observedView.addObserver(self, forKeyPath: "alpha", options: .new, context: &observerContext) 

をして、あなたのオブザーバー実装:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
    guard context == &observerContext else { 
     super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) 
     return 
    } 

    // do what you want here 
} 

注意を、オブザーバを削除することを忘れないでください。たとえば、deinitでないかもしれないこと:

deinit { 
    observedView.removeObserver(self, forKeyPath: "alpha", context: &observerContext) 
} 

注、スウィフト4に、このプロセスは少し簡略化されています。

private var token: NSKeyValueObservation? 

をそしてalpha財産を守ってください:あなたのオブザーバーを追跡するためにtokenプロパティを定義

token = observedView.observe(\.alpha) { [weak self] object, change in 
    // do something 
} 

注強い参照サイクルが発生しない閉鎖を確実にするために[weak self]の使用。明らかに、あなたがそのクロージャー内でselfを参照していない場合、それは必要ありません。

しかし、ブロックベースのパターンの長所は、(a)tokenが範囲外になると、オブザーバが自動的に削除されるため、特別なdeinitルーチンは必要ありません。 (b)observedViewの観察可能なキーが強く型付けされ、キーの単純な誤植を避けます。 (c)オブザーバーがこのクロージャーにリンクしているため、オブザーバーのコンテキストを確認する必要がなくなり、selfがこれを私たちのコンテキストではない場合は、呼び出す必要はありません。

+0

壮大!もちろん、それは 'forKeyPath:" alpha "'です。本当にありがとう。 – Fattie

関連する問題