Repository navigation
[ASPrimitiveTraitCollection] Always treat preferredContentSize as a potential nil #trivial - #757
Conversation
Add nil-value checks for preferredContentSizeCategory.
|
It seems better now when changing device orientation @ypogribnyi. Is there documentation around initializing ASPrimitiveTraitCollection? Might be missing something. We were seeing this on iOS 10 & 11. |
|
The preferred way to create By the way, why do we expose two trait collections interfaces ( |
Good questions! Based on facebookarchive/AsyncDisplayKit#1592, I think the original reason is to have ASTraitCollection as a friendly object-based API and ASPrimitiveTraitCollection as the internal actual struct that is used throughout the framework. We should at least document this reasoning, and/or move ASPrimitiveTraitCollection to a framework-private interface. |
nguyenhuy
left a comment
There was a problem hiding this comment.
@ypogribnyi Great reasoning on the possibility that ASPrimitiveTraitCollection may be initialized manually, and defend against such case.
@ay8s This PR should mitigate your crash, although I'd suggest to dig a bit deeper into your codebase and fix the root cause (initialize ASPrimitiveTraitCollection using the provided functions or better yet, switch to ASTraitCollection). Let us know what you find!
| #endif | ||
|
|
||
| @property (nonatomic, assign, readonly) UIContentSizeCategory preferredContentSizeCategory; | ||
| @property (nonatomic, assign, readonly) UIContentSizeCategory _Nonnull preferredContentSizeCategory; |
There was a problem hiding this comment.
I don't think we need _Nonnull annotations since we already use NS_ASSUME_NONNULL_BEGIN at the beginning of this file (here). It's always good to be defensive and guard against unexpected values in the implementation though.
| } else { | ||
| return AS_UIContentSizeCategoryUnspecified(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Nit, feel free to ignore this: It's a bit shorter to use ternary operator here, i.e:
return sizeCategory ? sizeCategory : AS_UIContentSizeCategoryUnspecified();
| .userInterfaceIdiom = UIUserInterfaceIdiomUnspecified, | ||
| .layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified, | ||
| .preferredContentSizeCategory = ASPrimitiveContentSizeCategoryMake(AS_UIContentSizeCategoryUnspecified()), | ||
| .preferredContentSizeCategory = AS_UIContentSizeCategoryUnspecified(), |
There was a problem hiding this comment.
Why do we remove the ASPrimitiveContentSizeCategoryMake in here. If you read the comment above ASPrimitiveContentSizeCategory we have to use ASPrimitiveContentSizeCategoryMake
* Mark [ASViewController overrideDisplayTraitsWithWindowSize] as deprecated. Code review changes: * Remove unneeded nonnull annotations * Add null check in ASTraitCollection constructor implementation * Codestyle * Add some documentation about ASPrimitiveTraitCollection vs ASTraitCollection usage
|
Thanks @ypogribnyi. We don't actually initialize either ASPrimitiveCollectionTraits or ASTraitCollection ourselves. I wonder if this might help with digging into the cause http://crashes.to/s/058c9ea3e54 |
|
@ay8s, thank you for your input! I finally managed to reproduce the crash. Looks like it occurs in I'm reproducing it on while having Although having a Anyways, this PR should fix the problem. |
|
Yup that'd be it! Thanks @ypogribnyi! |
| } | ||
| } | ||
|
|
||
| ASDISPLAYNODE_INLINE ASPrimitiveContentSizeCategory safePrimitiveContentSizeCategory(ASPrimitiveContentSizeCategory sizeCategory) { |
There was a problem hiding this comment.
I think we still should prefix this functions with AS
| .userInterfaceIdiom = UIUserInterfaceIdiomUnspecified, | ||
| .layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified, | ||
| .preferredContentSizeCategory = ASPrimitiveContentSizeCategoryMake(AS_UIContentSizeCategoryUnspecified()), | ||
| .preferredContentSizeCategory = AS_UIContentSizeCategoryUnspecified(), |
There was a problem hiding this comment.
Why do we remove the ASPrimitiveContentSizeCategoryMake in here. If you read the comment above ASPrimitiveContentSizeCategory we have to use ASPrimitiveContentSizeCategoryMake
|
|
||
| ASDISPLAYNODE_INLINE ASPrimitiveContentSizeCategory safePrimitiveContentSizeCategory(ASPrimitiveContentSizeCategory sizeCategory) { | ||
| return sizeCategory ? sizeCategory : AS_UIContentSizeCategoryUnspecified(); | ||
| } |
There was a problem hiding this comment.
I think in both cases we have to use ASPrimitiveContentSizeCategoryMake(AS_UIContentSizeCategoryUnspecified())
Remove safePrimitiveContentSizeCategory in favour of AS_safeContentSizeCategory.
nguyenhuy
left a comment
There was a problem hiding this comment.
Sorry for dropping the ball here, @ypogribnyi. LGTM now. Thanks!
…otential nil #trivial (TextureGroup#757) * Fix ASPrimitiveTraitCollection initialization on iOS 9. Add nil-value checks for preferredContentSizeCategory. * * Mark -[ASTraitCollection init] as deprecated. * Mark [ASViewController overrideDisplayTraitsWithWindowSize] as deprecated. Code review changes: * Remove unneeded nonnull annotations * Add null check in ASTraitCollection constructor implementation * Codestyle * Add some documentation about ASPrimitiveTraitCollection vs ASTraitCollection usage * Rename safeContentSizeCategory to AS_safeContentSizeCategory. Remove safePrimitiveContentSizeCategory in favour of AS_safeContentSizeCategory.
As
ASPrimitiveTraitCollectionis a struct, the application can always initialize it in its own way, without using Texture-provided initialization functions. This may lead topreferredContentSizefield beingnil, which, in turn, may lead to frustrating crashes when the struct is given to Texture.While simply advising the user to always use the provided initialization functions should solve the problem, it's better to always treat this structure as possibly improperly initialized and guard against
nilvalue in this field.Additionally this PR explicitly marks all
UIContentSizeCategoryusage inASTraitCollectionclass as non-null.