-
Notifications
You must be signed in to change notification settings - Fork 2.2k
[ASViewController] Add support for ASTraitCollection #1592
Conversation
#define ASDisplayTraitsCollectionTableSetEnvironmentState \ | ||
- (void)setEnvironmentState:(ASEnvironmentState)environmentState\ | ||
{\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need locking for setting and propagation?
@rcancro Overall seems good to me. Just one thing I'm thinking about is that the naming of the ASDisplayTraits is a bit different as all the other states that we start with "ASEnvironment..." Just thinking if we should internally use ASEnvironmentDisplayTraitsState and for the public API we expose it as displayTraits as we already do? cc @appleguy |
@maicki Thanks for the review! I've addressed most of your comments except for the request to make a NSObject-based class that wraps the struct. I'll look at that tomorrow |
[self progagateNewDisplayTraits:displayTraits]; | ||
} | ||
|
||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to implement all three of these notifications? willTransitionToTraitCollection:
should suffice, as it is called in transitionToSize:
call and is invoked before traitCollectionDidChange:
is called. I'd love to learn more about the reasons behind this implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that on start up of the app, traitCollectionDidChange:
is called, but not willTransitionToTraitCollection:
.
I also feel like i've seen the case where a window changes size (but not trait collection) and viewWillTransitionToSize:
is called but not willTransitionToTraitCollection:
.
progagateNewDisplayTraits:
does check to make sure that the traits are different before propagating, so even in the case where all three of these are called we only propagate once.
@rcancro I am re-running, but I think this may be a real failure. Probably worth opening the CarthageBuildTest to run it locally and see what the detailed failure is, and confirm the build server's result that before this change, it builds. It is possible that there is a new problem in master that hasn't been noticed yet though, as we did just adopt a new PINRemoteImage which apparently has some issue with Carthage. cc @garrettmoon ▸ Building Sample/CarthageExample [Debug] |
@rcancro @levi if ASDisplayTraits is directly analogous to UITraitCollection, can we call it ASTraitCollection instead? I assume it will be a struct directly inside ASEnvironment struct. Sincere apologies that I have not been able to review this yet. I really badly want to, but haven't been able to reach the minimum sleep quota recently even without touching ASDK diffs in the last week :(. Will plan to review on the plane on Friday or on return flight. |
@@ -24,8 +24,8 @@ final class ViewController: ASViewController, ASCollectionDelegate, ASCollection | |||
layout.minimumInteritemSpacing = padding | |||
layout.minimumLineSpacing = padding | |||
super.init(node: ASCollectionNode(collectionViewLayout: layout)) | |||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: .Plain, target: self, action: "didTapColorsButton") | |||
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Layout", style: .Plain, target: self, action: "didTapLayoutButton") | |||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Color", style: .Plain, target: self, action: #selector(didTapColorsButton)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs more indentation?
@rcancro looks like this patch got messed up with a rebase or merge. |
Initial attempt to get display traits working with ASEnvironment. To get proper ASDisplayTraits support, you must use an ASViewController. The ASViewController implements UITraitCollection-related methods (`traitCollectionDidChange:`, `willTransitionToTraitCollection:withTransitionCoordinator:`, viewWillTransitionToSize:withTransitionCoordinator`) to update the internal ASDisplayTraits and propagate them to subnodes. ASTableNode and ASCollectionNode don't actually have their cells as subnodes, so a little bit of trickery is involved (on `setEnvironment:` the table/collection node gets its data controllers completedNodes and propagates the new traits. see `ASDisplayTraitsCollectionTableSetEnvironmentState`). The data controller also passes the current display traits when creating new cells. ASViewController also supports the ability to return a custom set of display traits. So if you have a modal dialog that should always be told it is in a compact size class, you can set the override block before displaying the VC. A new example, called Display Traits, has been added. It shows how display traits can be used in a ASViewController with a normal ASDisplayNode as its root, as well as in ASViewControllers hosting table nodes and collection nodes. There is also an example of overriding the default display traits of a VC. Please provide feedback!
|
||
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(traitCollection, oldTraitCollection) == NO) { | ||
environmentState.traitCollection = traitCollection; | ||
[self.node setEnvironmentState:environmentState]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you able to use dot syntax here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean self.node.environmentState = environmentState
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
traitCollection.isMutable = NO; | ||
return [traitCollection environmentTraitCollection]; | ||
} | ||
return self.node.environmentState.traitCollection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to reduce the amount of references here. Perhaps add a shortcut to asdisplaynode to get the underlying environmentState trait collection?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@maicki had the idea to expose the trait collection as ASTraitCollection to the user, but store it as a struct behind the scenes. When providing a custom trait collection the user overrides one of two blocks, both of which return ASTraitCollection* not the struct.
I guess my point is that we are trying to make it difficult for the user to get to the struct trait collection since most obj-c developers are more familiar using classes. By adding a getter to the struct traits we kind of break that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could introduce it as a private method for these use cases.
* ASVC keeps a strong reference to the context to make sure that it stays alive. If you change this value | ||
* it will propagate the change to the subnodes. | ||
*/ | ||
@property (nonatomic, strong) id _Nullable traitColectionContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d'oh! good catch
Ricky, this is straight up poetry. |
Rotation, oh my |
- (void)setEnvironmentState:(ASEnvironmentState)environmentState\ | ||
{\ | ||
ASDN::MutexLocker l(lock);\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty damn fancy, sir @rcancro
Phenomenal work, @rcancro ! Once again, you've fundamentally extended the capabilities of the framework. I sincerely appreciate your attention to detail both in architecting and executing this. There's great care to efficiency / performance, but simultaneously a clear priority placed on a friendly object-based API. Love it. The only followup that seems important for the next 1-2 days is checking on the locking sites I commented at, but otherwise I think this is a mic drop. :) |
Summary: facebookarchive#1592 Reviewers: levi, scottg, garrett Reviewed By: garrett Differential Revision: https://phabricator.pinadmin.com/D90514
Initial attempt to get display traits working with ASEnvironment.
To get proper ASDisplayTraits support, you must use an ASViewController. The ASViewController implements UITraitCollection-related methods (
traitCollectionDidChange:
,willTransitionToTraitCollection:withTransitionCoordinator:
,viewWillTransitionToSize:withTransitionCoordinator
) to update the internal ASDisplayTraits and propagate them to subnodes.ASTableNode and ASCollectionNode don't actually have their cells as subnodes, so a little bit of trickery is involved (on
setEnvironment:
the table/collection node gets its data controller's completedNodes and propagates the new traits. seeASDisplayTraitsCollectionTableSetEnvironmentState
). The data controller also has the ability to get the current display traits when creating new cells through a new protocolASDataControllerEnvironmentDelegate
.ASViewController also supports the ability to return a custom set of display traits regardless its
UITraitCollection
. For example, if you have a modal dialog that should always have a compact size classes, you can set the override block before displaying the VC (overrideDisplayTraitsWithTraitCollection
andoverrideDisplayTraitsWithWindowSize
).A new example, called Display Traits, has been added. It shows how display traits can be used in a ASViewController with a normal ASDisplayNode as its root, as well as in ASViewControllers hosting a table node or collection node. There is also an example of overriding the default display traits of a VC.
Please provide any suggestions that you have!