xcode 使用 KVO 快速观察 contentSize (CGSize)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31421387/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
observing contentSize (CGSize) with KVO in swift
提问by Dennis Farandy
I'm trying to observering collectionView.contentSize
like this :
我正在尝试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)
}
}
}
and in xcode terminal I got a NSSize
not CGSize
like this :
在 xcode 终端中,我得到了一个NSSize
不CGSize
这样的:
Optional(["old": NSSize: {320, 0}, "new": NSSize: {375, 39.5}, "kind": 1])
In objective-c I used method CGSizeValue
在objective-c中我使用了方法 CGSizeValue
CGSize newContentSize = [[change objectForKey:NSKeyValueChangeNewKey] CGSizeValue];
Is there any method like CGSizeValue
in swift
有没有像CGSizeValue
swift一样的方法
I have tried in swift var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
but got error
我试过快速var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
但出错
could not find member 'CGSizeValue'
找不到成员“CGSizeValue”
need help anyone? Thanks
需要帮助任何人?谢谢
采纳答案by Bluezen
Are you on iOS? Because I am, I did the same thing and arrived at the same question; why NSSize
? Maybe that's just the xcode terminal playing a trick on us.
你在iOS上吗?因为我是,所以我做了同样的事情并得出了同样的问题;为什么NSSize
?也许这只是 xcode 终端在欺骗我们。
Anyway, you can cast it to an NSValue
then you will be able to use CGSizeValue
:
无论如何,您可以将其转换为 anNSValue
然后您将能够使用CGSizeValue
:
if let zeChange = change as? [NSString: NSValue] {
let oldSize = zeChange[NSKeyValueChangeOldKey]?.CGSizeValue()
let newSize = zeChange[NSKeyValueChangeNewKey]?.CGSizeValue()
}
回答by Imanou Petit
With Swift 4, you can cast the result of the change
dictionary for the key NSKeyValueChangeKey.newKey
as being of type CGSize
:
使用 Swift 4,您可以将change
键的字典结果转换NSKeyValueChangeKey.newKey
为类型CGSize
:
if let size = change?[NSKeyValueChangeKey.newKey] as? CGSize {
/* ... */
}
The following UIViewController
implementation shows how to set a KVO stack in order to observe the changes of the contentSize
property of any UIScrollView
subclass (e.g UITextView
):
以下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))
}
}
Note that with Swift 4, as an alternative to addObserver(_:, forKeyPath:, options:, context:)
and observeValue(forKeyPath:, of:, change:, context:)
, you can use observe(_:, options:, changeHandler:)
in order to track your UIScrollView
subclass contentSize
property changes:
需要注意的是斯威夫特与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)
}
}
回答by Dharmesh Kheni
Check out this example code:
查看此示例代码:
if context == ApprovalObservingContext{
if let theChange = change as? [NSString: Bool]{
var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue()
}
}
This is not giving any error.
这没有给出任何错误。
回答by Demosthese
There's a simpler and arguably swiftier alternative.
有一个更简单且可以说更快捷的替代方案。
You can subclass UICollectionViewLayout
(or any of its subclasses, like UICollectionViewFlowLayout
) and override a computed property collectionViewContentSize
. By calling super
you'll get the contentSize of your collection and be able to delegate this value back to your code.
您可以子类化UICollectionViewLayout
(或其任何子类,如UICollectionViewFlowLayout
)并覆盖计算属性collectionViewContentSize
。通过调用,super
您将获得集合的 contentSize 并能够将此值委托回您的代码。
So you'll have something like this:
所以你会有这样的事情:
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
}
}