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