I'm trying to observering collectionView.contentSize like this :
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 :
Optional(["old": NSSize: {320, 0}, "new": NSSize: {375, 39.5}, "kind": 1])
In objective-c I used method CGSizeValue
CGSize newContentSize = [[change objectForKey:NSKeyValueChangeNewKey] CGSizeValue];
Is there any method like CGSizeValue in swift
I have tried in swift var newContentSize = change[NSKeyValueChangeNewKey]?.CGSizeValue() but got error
could not find member 'CGSizeValue'
need help anyone? Thanks
With Swift 4, you can cast the result of the change dictionary for the key NSKeyValueChangeKey.newKey as being of type 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):
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:
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)
}
}
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.
Anyway, you can cast it to an NSValue then you will be able to use CGSizeValue:
if let zeChange = change as? [NSString: NSValue] {
let oldSize = zeChange[NSKeyValueChangeOldKey]?.CGSizeValue()
let newSize = zeChange[NSKeyValueChangeNewKey]?.CGSizeValue()
}
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.
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With