Rxswift: How to subscript UIScrollView's contentSize change Observable

Created on 23 Nov 2015  Â·  13Comments  Â·  Source: ReactiveX/RxSwift

How to subscript UIScrollView's contentSize change Observable?

Most helpful comment

I don't think the usefulness of some hack even matters, I'm calling a hack some usage of the API that is not officially supported. As far as I'm aware of using "contentSize" KVO is a hack.

The problem for including hacks in this library is obvious. Once we add some API and it's discoverable through autocomplete, people will just use it, and if the time when this hack breaks comes, they will report bugs to us and blame us. There will probably be also ton of ugly code to maintain it.

There are multiple other reasons why this might be a bad idea:

  • if you are using it that way, it will probably cause glitches
  • it might be prudent to use something better than autolayout

Having said that... Would I consider using KVO for contentSize after I've tried more appropriate solutions, as a last resort? Sure, there comes a time when it's reasonable to give up, and hack something.

But when somebody does that hack for their project, they are responsible for maintaining it, not us.

All 13 comments

yourScrollView.rx_contentOffset.asObservable() gives you an Observable<CGPoint>, you can then .subscribe in one of its flavors

@carlosypunto what i want is contentSize,not contentOffset

Sorry, where I've the head. Now there is now a KVO possibility with rx_observe(CGSize.self, "contentSize"). But we'll see how to improve it.

@carlosypunto thank you ~ it works~

or rx_observe(contentSize.dynamicType, "contentSize")

Hi @zixun ,

although this is technically possible, I wouldn't suggest you observe contentSize of UIScrollView.

Although the classes of the UIKit framework generally do not support KVO, you can still implement it in the custom objects of your application, including custom views.

  • contentSize should be bound to some other place of truth. contentSize should be ideally just a cache for that source of truth. My advice is to observe that place of truth directly.
    I would consider observing properties of UIViews that user can't edit by his actions directly kind of a code smell :) It might work, but ... you can probably figure out a more appropriate way to observe things :)

That being said, this method should work :)

I think we can close this one also :)

contentSize should be bound to some other place of truth.

But that source of truth may be a value generated by autolayout at runtime.

I don’t have a trademark on place of truth, but the way I think about it is that all of the data needed to reproduce the screen on any device is “the truth”.

The fact that you’ve chosen auto layout as a way to calculate layout, and you need an intermediate layout calculation result in part of a rendering process, and Apple has tied layout calculation to main thread and UIView hierarchy doesn’t IMHO change what I call “the truth”.

Maybe I am misunderstanding your point, but what I was responding to is the question of whether it is useful / necessary to observe contentSize on scrollviews. It sounded to me like you were saying that it is unnecessary because the client code should always be able to go to some underlying data that determines the size, rather than observing the view size itself. While that sounds plausible, what I am suggesting is that there are at least a few legitimate cases where the observing code may not have access to the size information in any other way: 1) When the contentSize is determined by AutoLayout it may be impractical for the client to reproduce that calculation (hence the "source of truth" is AutoLayout in that case). 2) If you are building a framework that simply does not have access to the logic that sets up the scrollview. e.g. I recently created something similar to the Twitter profile scrolling behavior with the collapsing header. To create that in reasonable way I do not want my "outer" scrolling logic to have to be linked to the logic that determines the child sizes... I simply want to observe the child sizes.

As you pointed out it is possible to observe with KVO and that is fine... It would just be convenient to have it wrapped with Rx for consistency.

I don't think the usefulness of some hack even matters, I'm calling a hack some usage of the API that is not officially supported. As far as I'm aware of using "contentSize" KVO is a hack.

The problem for including hacks in this library is obvious. Once we add some API and it's discoverable through autocomplete, people will just use it, and if the time when this hack breaks comes, they will report bugs to us and blame us. There will probably be also ton of ugly code to maintain it.

There are multiple other reasons why this might be a bad idea:

  • if you are using it that way, it will probably cause glitches
  • it might be prudent to use something better than autolayout

Having said that... Would I consider using KVO for contentSize after I've tried more appropriate solutions, as a last resort? Sure, there comes a time when it's reasonable to give up, and hack something.

But when somebody does that hack for their project, they are responsible for maintaining it, not us.

As far as I'm aware of using "contentSize" KVO is a hack.

I agree and that is a perfectly valid reason not to use it in the Rx API. Maybe there is something else we can wrap or observe to infer when content size has changed? I haven't really investigated, so maybe there is not. Again, I was just giving a rational for why one would want to do it. I'm not really sure why this is such a contentious issue :) Thanks for your work on Rx.

This was an interesting read because both sides of the argument are valid. Although it's possible (and not a hack) to observe UIScrollView contentSize for changes; if you find yourself needing to do this then it's likely you have gone in the wrong direction for a while.

Try tearing back some of your UI and using child view controllers to tie into the UIContentContainer protocol where you can observe the preferred content size changes (which can be set via didLayoutSubviews or viewWillTransition or traitcollectiondidchange) of child view controller and then subsequently adjust your constraints from there (like a puppet-master).

Was this page helpful?
0 / 5 - 0 ratings