用swift中的KVO观察contentSize(CGSize)

问题描述 投票:4回答:4

我试图像这样观察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这样的方法

我曾尝试过快速的var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue(),但得到了错误

找不到会员'CGSizeValue'

需要帮助吗?谢谢

xcode swift key-value-observing
4个回答
2
投票

你在iOS上吗?因为我,我做了同样的事情,并得出了同样的问题;为什么NSSize?也许这就是xcode终端对我们起作用的伎俩。

无论如何,你可以把它投射到NSValue,然后你就可以使用CGSizeValue

if let zeChange = change as? [NSString: NSValue] {
    let oldSize = zeChange[NSKeyValueChangeOldKey]?.CGSizeValue()
    let newSize = zeChange[NSKeyValueChangeNewKey]?.CGSizeValue()
}

7
投票

使用Swift 4,您可以将关键changeNSKeyValueChangeKey.newKey字典的结果转换为CGSize类型:

if let size = change?[NSKeyValueChangeKey.newKey] as? CGSize {
    /* ... */
}

以下UIViewController实现显示如何设置KVO堆栈以观察任何contentSize子类(例如UIScrollView)的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)
    }

}

0
投票

看看这个示例代码:

if context == ApprovalObservingContext{
        if let theChange = change as? [NSString: Bool]{

            var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
        }
    }

这没有给出任何错误。


0
投票

有一个更简单,可以说更快捷的选择。

您可以继承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
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.