在 swift 中使用 KVO 观察 contentSize (CGSize)
observing contentSize (CGSize) with KVO in swift
我正在尝试这样观察 collectionView.contentSize
:
func startObserveCollectionView() {
collectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old.union(NSKeyValueObservingOptions.New), context: &SearchDasboardLabelContext)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if context == &SearchDasboardLabelContext {
if object === collectionView && keyPath! == "contentSize" {
print(change)
}
}
}
并且在 xcode 终端中我得到了一个 NSSize
而不是 CGSize
像这样:
Optional(["old": NSSize: {320, 0}, "new": NSSize: {375, 39.5}, "kind": 1])
在objective-c中我使用了方法CGSizeValue
CGSize newContentSize = [[change objectForKey:NSKeyValueChangeNewKey] CGSizeValue];
swift
中有没有类似CGSizeValue
的方法
我在 swift var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
中尝试过,但出现错误
could not find member 'CGSizeValue'
有人需要帮助吗?谢谢
查看此示例代码:
if context == ApprovalObservingContext{
if let theChange = change as? [NSString: Bool]{
var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
}
}
这没有给出任何错误。
你在iOS吗?因为我是,所以我做了同样的事情并得出了同样的问题;为什么 NSSize
?也许这只是 xcode 终端在耍我们。
无论如何,您可以将其转换为 NSValue
然后您将能够使用 CGSizeValue
:
if let zeChange = change as? [NSString: NSValue] {
let oldSize = zeChange[NSKeyValueChangeOldKey]?.CGSizeValue()
let newSize = zeChange[NSKeyValueChangeNewKey]?.CGSizeValue()
}
使用 Swift 4,您可以将键 NSKeyValueChangeKey.newKey
的 change
字典的结果转换为类型 CGSize
:
if let size = change?[NSKeyValueChangeKey.newKey] as? CGSize {
/* ... */
}
下面的 UIViewController
实现展示了如何设置 KVO 堆栈以观察任何 UIScrollView
子类的 contentSize
属性 的变化(例如 UITextView
):
import UIKit
private var myContext = 0
class ViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
/* ... */
override func viewDidLoad() {
super.viewDidLoad()
textView.addObserver(self, forKeyPath: #keyPath(UITextView.contentSize), options: [NSKeyValueObservingOptions.new], context: &myContext)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &myContext,
keyPath == #keyPath(UITextView.contentSize),
let contentSize = change?[NSKeyValueChangeKey.newKey] as? CGSize {
print("contentSize:", contentSize)
}
}
deinit {
textView.removeObserver(self, forKeyPath: #keyPath(UITextView.contentSize))
}
}
请注意,对于 Swift 4,作为 addObserver(_:, forKeyPath:, options:, context:)
和 observeValue(forKeyPath:, of:, change:, context:)
的替代方案,您可以使用 observe(_:, options:, changeHandler:)
来跟踪您的 UIScrollView
子类contentSize
属性 变化:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
var observer: NSKeyValueObservation?
/* ... */
override func viewDidLoad() {
super.viewDidLoad()
let handler = { (textView: UITextView, change: NSKeyValueObservedChange<CGSize>) in
if let contentSize = change.newValue {
print("contentSize:", contentSize)
}
}
observer = textView.observe(\UITextView.contentSize, options: [NSKeyValueObservingOptions.new], changeHandler: handler)
}
}
有一个更简单且可以说更快捷的替代方案。
您可以子类化 UICollectionViewLayout
(或其任何子类,如 UICollectionViewFlowLayout
)并覆盖计算的 属性 collectionViewContentSize
。通过调用 super
,您将获得集合的 contentSize,并能够将此值委托回您的代码。
所以你会有这样的东西:
protocol FlowLayoutDelegate: class {
func collectionView(_ collectionView: UICollectionView?, didChange contentSize: CGSize)
}
class FlowLayout: UICollectionViewFlowLayout {
weak var delegate: FlowLayoutDelegate?
override var collectionViewContentSize: CGSize {
let contentSize = super.collectionViewContentSize
delegate?.collectionView(collectionView, didChange: contentSize)
return contentSize
}
}
我正在尝试这样观察 collectionView.contentSize
:
func startObserveCollectionView() {
collectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old.union(NSKeyValueObservingOptions.New), context: &SearchDasboardLabelContext)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if context == &SearchDasboardLabelContext {
if object === collectionView && keyPath! == "contentSize" {
print(change)
}
}
}
并且在 xcode 终端中我得到了一个 NSSize
而不是 CGSize
像这样:
Optional(["old": NSSize: {320, 0}, "new": NSSize: {375, 39.5}, "kind": 1])
在objective-c中我使用了方法CGSizeValue
CGSize newContentSize = [[change objectForKey:NSKeyValueChangeNewKey] CGSizeValue];
swift
中有没有类似CGSizeValue
的方法
我在 swift var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
中尝试过,但出现错误
could not find member 'CGSizeValue'
有人需要帮助吗?谢谢
查看此示例代码:
if context == ApprovalObservingContext{
if let theChange = change as? [NSString: Bool]{
var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
}
}
这没有给出任何错误。
你在iOS吗?因为我是,所以我做了同样的事情并得出了同样的问题;为什么 NSSize
?也许这只是 xcode 终端在耍我们。
无论如何,您可以将其转换为 NSValue
然后您将能够使用 CGSizeValue
:
if let zeChange = change as? [NSString: NSValue] {
let oldSize = zeChange[NSKeyValueChangeOldKey]?.CGSizeValue()
let newSize = zeChange[NSKeyValueChangeNewKey]?.CGSizeValue()
}
使用 Swift 4,您可以将键 NSKeyValueChangeKey.newKey
的 change
字典的结果转换为类型 CGSize
:
if let size = change?[NSKeyValueChangeKey.newKey] as? CGSize {
/* ... */
}
下面的 UIViewController
实现展示了如何设置 KVO 堆栈以观察任何 UIScrollView
子类的 contentSize
属性 的变化(例如 UITextView
):
import UIKit
private var myContext = 0
class ViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
/* ... */
override func viewDidLoad() {
super.viewDidLoad()
textView.addObserver(self, forKeyPath: #keyPath(UITextView.contentSize), options: [NSKeyValueObservingOptions.new], context: &myContext)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &myContext,
keyPath == #keyPath(UITextView.contentSize),
let contentSize = change?[NSKeyValueChangeKey.newKey] as? CGSize {
print("contentSize:", contentSize)
}
}
deinit {
textView.removeObserver(self, forKeyPath: #keyPath(UITextView.contentSize))
}
}
请注意,对于 Swift 4,作为 addObserver(_:, forKeyPath:, options:, context:)
和 observeValue(forKeyPath:, of:, change:, context:)
的替代方案,您可以使用 observe(_:, options:, changeHandler:)
来跟踪您的 UIScrollView
子类contentSize
属性 变化:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
var observer: NSKeyValueObservation?
/* ... */
override func viewDidLoad() {
super.viewDidLoad()
let handler = { (textView: UITextView, change: NSKeyValueObservedChange<CGSize>) in
if let contentSize = change.newValue {
print("contentSize:", contentSize)
}
}
observer = textView.observe(\UITextView.contentSize, options: [NSKeyValueObservingOptions.new], changeHandler: handler)
}
}
有一个更简单且可以说更快捷的替代方案。
您可以子类化 UICollectionViewLayout
(或其任何子类,如 UICollectionViewFlowLayout
)并覆盖计算的 属性 collectionViewContentSize
。通过调用 super
,您将获得集合的 contentSize,并能够将此值委托回您的代码。
所以你会有这样的东西:
protocol FlowLayoutDelegate: class {
func collectionView(_ collectionView: UICollectionView?, didChange contentSize: CGSize)
}
class FlowLayout: UICollectionViewFlowLayout {
weak var delegate: FlowLayoutDelegate?
override var collectionViewContentSize: CGSize {
let contentSize = super.collectionViewContentSize
delegate?.collectionView(collectionView, didChange: contentSize)
return contentSize
}
}