[ASPrimitiveTraitCollection] Always treat preferredContentSize as a potential nil #trivial (#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.
This commit is contained in:
Yevgen Pogribnyi
2018-03-21 14:44:30 +02:00
committed by Huy Nguyen
parent 5385d8b3ed
commit e954b1045a
3 changed files with 208 additions and 140 deletions

View File

@@ -63,7 +63,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Set this block to customize the ASDisplayTraits returned when the VC transitions to the given window size.
*/
@property (nonatomic, copy) ASDisplayTraitsForTraitWindowSizeBlock overrideDisplayTraitsWithWindowSize;
@property (nonatomic, copy) ASDisplayTraitsForTraitWindowSizeBlock overrideDisplayTraitsWithWindowSize ASDISPLAYNODE_DEPRECATED_MSG("This property is actually never accessed inside the framework");
/**
* @abstract Passthrough property to the the .interfaceState of the node.

View File

@@ -58,6 +58,14 @@ extern ASPrimitiveContentSizeCategory ASPrimitiveContentSizeCategoryMake(UIConte
#pragma mark - ASPrimitiveTraitCollection
/**
* @abstract This is an internal struct-representation of ASTraitCollection.
*
* @discussion This struct is for internal use only. Framework users should always use ASTraitCollection.
*
* If you use ASPrimitiveTraitCollection, please do make sure to initialize it with ASPrimitiveTraitCollectionMakeDefault()
* or ASPrimitiveTraitCollectionFromUITraitCollection(UITraitCollection*).
*/
typedef struct ASPrimitiveTraitCollection {
UIUserInterfaceSizeClass horizontalSizeClass;
UIUserInterfaceSizeClass verticalSizeClass;
@@ -112,17 +120,23 @@ ASDISPLAYNODE_EXTERN_C_END
@protocol ASTraitEnvironment <NSObject>
/**
* Returns a struct-representation of the environment's ASEnvironmentDisplayTraits. This only exists as a internal
* convenience method. Users should access the trait collections through the NSObject based asyncTraitCollection API
* @abstract Returns a struct-representation of the environment's ASEnvironmentDisplayTraits.
*
* @discussion This only exists as an internal convenience method. Users should access the trait collections through
* the NSObject based asyncTraitCollection API
*/
- (ASPrimitiveTraitCollection)primitiveTraitCollection;
/**
* Sets a trait collection on this environment state.
* @abstract Sets a trait collection on this environment state.
*
* @discussion This only exists as an internal convenience method. Users should not override trait collection using it.
* Use [ASViewController overrideDisplayTraitsWithTraitCollection] block instead.
*/
- (void)setPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traitCollection;
/**
* @abstract Returns the thread-safe UITraitCollection equivalent.
*/
- (ASTraitCollection *)asyncTraitCollection;
@@ -179,8 +193,6 @@ AS_SUBCLASSING_RESTRICTED
@property (nonatomic, assign, readonly) CGSize containerSize;
+ (ASTraitCollection *)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits;
+ (ASTraitCollection *)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
containerSize:(CGSize)windowSize;
@@ -211,13 +223,25 @@ AS_SUBCLASSING_RESTRICTED
containerSize:(CGSize)windowSize;
#endif
- (ASPrimitiveTraitCollection)primitiveTraitCollection;
- (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection;
@end
/**
* These are internal helper methods. Should never be called by the framework users.
*/
@interface ASTraitCollection (PrimitiveTraits)
+ (ASTraitCollection *)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits;
- (ASPrimitiveTraitCollection)primitiveTraitCollection;
@end
@interface ASTraitCollection (Deprecated)
- (instancetype)init ASDISPLAYNODE_DEPRECATED_MSG("The default constructor of this class is going to become unavailable. Use other constructors instead.");
+ (ASTraitCollection *)traitCollectionWithDisplayScale:(CGFloat)displayScale
userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass

View File

@@ -32,6 +32,10 @@ ASDISPLAYNODE_INLINE UIContentSizeCategory AS_UIContentSizeCategoryUnspecified()
}
}
ASDISPLAYNODE_INLINE UIContentSizeCategory _Nonnull AS_safeContentSizeCategory(UIContentSizeCategory _Nullable sizeCategory) {
return sizeCategory ? sizeCategory : AS_UIContentSizeCategoryUnspecified();
}
ASPrimitiveContentSizeCategory ASPrimitiveContentSizeCategoryMake(UIContentSizeCategory sizeCategory) {
if ([sizeCategory isEqualToString:UIContentSizeCategoryExtraSmall]) {
return UIContentSizeCategoryExtraSmall;
@@ -115,13 +119,15 @@ ASPrimitiveTraitCollection ASPrimitiveTraitCollectionFromUITraitCollection(UITra
#if TARGET_OS_TV
environmentTraitCollection.userInterfaceStyle = traitCollection.userInterfaceStyle;
#endif
} else {
environmentTraitCollection.displayGamut = UIDisplayGamutSRGB; // We're on iOS 9 or lower, so this is not a P3 device.
}
return environmentTraitCollection;
}
BOOL ASPrimitiveTraitCollectionIsEqualToASPrimitiveTraitCollection(ASPrimitiveTraitCollection lhs, ASPrimitiveTraitCollection rhs) {
UIContentSizeCategory leftSizeCategory = (UIContentSizeCategory)lhs.preferredContentSizeCategory;
UIContentSizeCategory rightSizeCategory = (UIContentSizeCategory)rhs.preferredContentSizeCategory;
UIContentSizeCategory leftSizeCategory = AS_safeContentSizeCategory(lhs.preferredContentSizeCategory);
UIContentSizeCategory rightSizeCategory = AS_safeContentSizeCategory(rhs.preferredContentSizeCategory);
return
lhs.verticalSizeClass == rhs.verticalSizeClass &&
@@ -230,7 +236,7 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
#if TARGET_OS_TV
[props addObject:@{ @"userInterfaceStyle": AS_NSStringFromUIUserInterfaceStyle(traits.userInterfaceStyle) }];
#endif
[props addObject:@{ @"preferredContentSizeCategory": (UIContentSizeCategory)traits.preferredContentSizeCategory }];
[props addObject:@{ @"preferredContentSizeCategory": AS_safeContentSizeCategory(traits.preferredContentSizeCategory) }];
[props addObject:@{ @"containerSize": NSStringFromCGSize(traits.containerSize) }];
return ASObjectDescriptionMakeWithoutObject(props);
}
@@ -249,7 +255,7 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection
userInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle
preferredContentSizeCategory:(UIContentSizeCategory)preferredContentSizeCategory
preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory
containerSize:(CGSize)windowSize
{
self = [super init];
@@ -262,7 +268,7 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
_forceTouchCapability = forceTouchCapability;
_layoutDirection = layoutDirection;
_userInterfaceStyle = userInterfaceStyle;
_preferredContentSizeCategory = preferredContentSizeCategory;
_preferredContentSizeCategory = AS_safeContentSizeCategory(preferredContentSizeCategory); // guard against misuse
_containerSize = windowSize;
}
return self;
@@ -276,7 +282,7 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection
userInterfaceStyle:(UIUserInterfaceStyle)userInterfaceStyle
preferredContentSizeCategory:(UIContentSizeCategory)preferredContentSizeCategory
preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory
containerSize:(CGSize)windowSize
{
return [[self alloc] initWithHorizontalSizeClass:horizontalSizeClass
@@ -300,7 +306,7 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection
preferredContentSizeCategory:(UIContentSizeCategory)preferredContentSizeCategory
preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory
containerSize:(CGSize)windowSize
{
self = [super init];
@@ -312,7 +318,7 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
_userInterfaceIdiom = userInterfaceIdiom;
_forceTouchCapability = forceTouchCapability;
_layoutDirection = layoutDirection;
_preferredContentSizeCategory = preferredContentSizeCategory;
_preferredContentSizeCategory = AS_safeContentSizeCategory(preferredContentSizeCategory); // guard against misuse
_containerSize = windowSize;
}
return self;
@@ -325,7 +331,7 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
forceTouchCapability:(UIForceTouchCapability)forceTouchCapability
layoutDirection:(UITraitEnvironmentLayoutDirection)layoutDirection
preferredContentSizeCategory:(UIContentSizeCategory)preferredContentSizeCategory
preferredContentSizeCategory:(UIContentSizeCategory _Nonnull)preferredContentSizeCategory
containerSize:(CGSize)windowSize
{
return [[self alloc] initWithHorizontalSizeClass:horizontalSizeClass
@@ -341,6 +347,168 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
#endif
+ (instancetype)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
containerSize:(CGSize)windowSize
{
return [self traitCollectionWithUITraitCollection:traitCollection
containerSize:windowSize
fallbackContentSizeCategory:AS_UIContentSizeCategoryUnspecified()];
}
+ (instancetype)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
containerSize:(CGSize)windowSize
fallbackContentSizeCategory:(UIContentSizeCategory _Nonnull)fallbackContentSizeCategory
{
UIDisplayGamut displayGamut;
UITraitEnvironmentLayoutDirection layoutDirection;
UIContentSizeCategory sizeCategory;
#if TARGET_OS_TV
UIUserInterfaceStyle userInterfaceStyle;
#endif
if (AS_AVAILABLE_IOS(10)) {
displayGamut = traitCollection.displayGamut;
layoutDirection = traitCollection.layoutDirection;
sizeCategory = traitCollection.preferredContentSizeCategory;
#if TARGET_OS_TV
userInterfaceStyle = traitCollection.userInterfaceStyle;
#endif
} else {
displayGamut = UIDisplayGamutSRGB; // We're on iOS 9 or lower, so this is not a P3 device.
layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified;
sizeCategory = fallbackContentSizeCategory;
#if TARGET_OS_TV
userInterfaceStyle = UIUserInterfaceStyleUnspecified;
#endif
}
#if TARGET_OS_TV
return [self traitCollectionWithHorizontalSizeClass:traitCollection.horizontalSizeClass
verticalSizeClass:traitCollection.verticalSizeClass
displayScale:traitCollection.displayScale
displayGamut:displayGamut
userInterfaceIdiom:traitCollection.userInterfaceIdiom
forceTouchCapability:traitCollection.forceTouchCapability
layoutDirection:layoutDirection
userInterfaceStyle:userInterfaceStyle
preferredContentSizeCategory:sizeCategory
containerSize:windowSize];
#else
return [self traitCollectionWithHorizontalSizeClass:traitCollection.horizontalSizeClass
verticalSizeClass:traitCollection.verticalSizeClass
displayScale:traitCollection.displayScale
displayGamut:displayGamut
userInterfaceIdiom:traitCollection.userInterfaceIdiom
forceTouchCapability:traitCollection.forceTouchCapability
layoutDirection:layoutDirection
preferredContentSizeCategory:sizeCategory
containerSize:windowSize];
#endif
}
- (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection
{
if (traitCollection == nil) {
return NO;
}
if (self == traitCollection) {
return YES;
}
return
self.horizontalSizeClass == traitCollection.horizontalSizeClass &&
self.verticalSizeClass == traitCollection.verticalSizeClass &&
self.displayScale == traitCollection.displayScale &&
self.displayGamut == traitCollection.displayGamut &&
self.userInterfaceIdiom == traitCollection.userInterfaceIdiom &&
self.forceTouchCapability == traitCollection.forceTouchCapability &&
self.layoutDirection == traitCollection.layoutDirection &&
#if TARGET_OS_TV
self.userInterfaceStyle == traitCollection.userInterfaceStyle &&
#endif
[self.preferredContentSizeCategory isEqualToString:traitCollection.preferredContentSizeCategory] &&
CGSizeEqualToSize(self.containerSize, traitCollection.containerSize);
}
@end
@implementation ASTraitCollection (PrimitiveTraits)
+ (instancetype)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits
{
#if TARGET_OS_TV
return [self traitCollectionWithHorizontalSizeClass:traits.horizontalSizeClass
verticalSizeClass:traits.verticalSizeClass
displayScale:traits.displayScale
displayGamut:traits.displayGamut
userInterfaceIdiom:traits.userInterfaceIdiom
forceTouchCapability:traits.forceTouchCapability
layoutDirection:traits.layoutDirection
userInterfaceStyle:traits.userInterfaceStyle
preferredContentSizeCategory:AS_safeContentSizeCategory(traits.preferredContentSizeCategory)
containerSize:traits.containerSize];
#else
return [self traitCollectionWithHorizontalSizeClass:traits.horizontalSizeClass
verticalSizeClass:traits.verticalSizeClass
displayScale:traits.displayScale
displayGamut:traits.displayGamut
userInterfaceIdiom:traits.userInterfaceIdiom
forceTouchCapability:traits.forceTouchCapability
layoutDirection:traits.layoutDirection
preferredContentSizeCategory:AS_safeContentSizeCategory(traits.preferredContentSizeCategory)
containerSize:traits.containerSize];
#endif
}
- (ASPrimitiveTraitCollection)primitiveTraitCollection
{
return (ASPrimitiveTraitCollection) {
.horizontalSizeClass = self.horizontalSizeClass,
.verticalSizeClass = self.verticalSizeClass,
.displayScale = self.displayScale,
.displayGamut = self.displayGamut,
.userInterfaceIdiom = self.userInterfaceIdiom,
.forceTouchCapability = self.forceTouchCapability,
.layoutDirection = self.layoutDirection,
#if TARGET_OS_TV
.userInterfaceStyle = self.userInterfaceStyle,
#endif
.preferredContentSizeCategory = ASPrimitiveContentSizeCategoryMake(self.preferredContentSizeCategory),
.containerSize = self.containerSize,
};
}
@end
@implementation ASTraitCollection (Deprecated)
- (instancetype)init
{
#if TARGET_OS_TV
return [self initWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified
verticalSizeClass:UIUserInterfaceSizeClassUnspecified
displayScale:0
displayGamut:UIDisplayGamutUnspecified
userInterfaceIdiom:UIUserInterfaceIdiomUnspecified
forceTouchCapability:UIForceTouchCapabilityUnknown
layoutDirection:UITraitEnvironmentLayoutDirectionUnspecified
userInterfaceStyle:UIUserInterfaceStyleUnspecified
preferredContentSizeCategory:AS_UIContentSizeCategoryUnspecified()
containerSize:CGSizeZero];
#else
return [self initWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified
verticalSizeClass:UIUserInterfaceSizeClassUnspecified
displayScale:0
displayGamut:UIDisplayGamutUnspecified
userInterfaceIdiom:UIUserInterfaceIdiomUnspecified
forceTouchCapability:UIForceTouchCapabilityUnknown
layoutDirection:UITraitEnvironmentLayoutDirectionUnspecified
preferredContentSizeCategory:AS_UIContentSizeCategoryUnspecified()
containerSize:CGSizeZero];
#endif
}
+ (ASTraitCollection *)traitCollectionWithDisplayScale:(CGFloat)displayScale
userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
horizontalSizeClass:(UIUserInterfaceSizeClass)horizontalSizeClass
@@ -372,128 +540,4 @@ NSString *NSStringFromASPrimitiveTraitCollection(ASPrimitiveTraitCollection trai
#endif
}
+ (instancetype)traitCollectionWithASPrimitiveTraitCollection:(ASPrimitiveTraitCollection)traits
{
#if TARGET_OS_TV
return [self traitCollectionWithHorizontalSizeClass:traits.horizontalSizeClass
verticalSizeClass:traits.verticalSizeClass
displayScale:traits.displayScale
displayGamut:traits.displayGamut
userInterfaceIdiom:traits.userInterfaceIdiom
forceTouchCapability:traits.forceTouchCapability
layoutDirection:traits.layoutDirection
userInterfaceStyle:traits.userInterfaceStyle
preferredContentSizeCategory:(UIContentSizeCategory)traits.preferredContentSizeCategory
containerSize:traits.containerSize];
#else
return [self traitCollectionWithHorizontalSizeClass:traits.horizontalSizeClass
verticalSizeClass:traits.verticalSizeClass
displayScale:traits.displayScale
displayGamut:traits.displayGamut
userInterfaceIdiom:traits.userInterfaceIdiom
forceTouchCapability:traits.forceTouchCapability
layoutDirection:traits.layoutDirection
preferredContentSizeCategory:(UIContentSizeCategory)traits.preferredContentSizeCategory
containerSize:traits.containerSize];
#endif
}
+ (instancetype)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
containerSize:(CGSize)windowSize
{
return [self traitCollectionWithUITraitCollection:traitCollection
containerSize:windowSize
fallbackContentSizeCategory:AS_UIContentSizeCategoryUnspecified()];
}
+ (instancetype)traitCollectionWithUITraitCollection:(UITraitCollection *)traitCollection
containerSize:(CGSize)windowSize
fallbackContentSizeCategory:(UIContentSizeCategory)fallbackContentSizeCategory
{
UIDisplayGamut displayGamut;
UITraitEnvironmentLayoutDirection layoutDirection;
UIContentSizeCategory sizeCategory;
#if TARGET_OS_TV
UIUserInterfaceStyle userInterfaceStyle;
#endif
if (AS_AVAILABLE_IOS(10)) {
displayGamut = traitCollection.displayGamut;
layoutDirection = traitCollection.layoutDirection;
sizeCategory = traitCollection.preferredContentSizeCategory;
#if TARGET_OS_TV
userInterfaceStyle = traitCollection.userInterfaceStyle;
#endif
} else {
displayGamut = UIDisplayGamutUnspecified;
layoutDirection = UITraitEnvironmentLayoutDirectionUnspecified;
sizeCategory = fallbackContentSizeCategory;
#if TARGET_OS_TV
userInterfaceStyle = UIUserInterfaceStyleUnspecified;
#endif
}
#if TARGET_OS_TV
return [self traitCollectionWithHorizontalSizeClass:traitCollection.horizontalSizeClass
verticalSizeClass:traitCollection.verticalSizeClass
displayScale:traitCollection.displayScale
displayGamut:displayGamut
userInterfaceIdiom:traitCollection.userInterfaceIdiom
forceTouchCapability:traitCollection.forceTouchCapability
layoutDirection:layoutDirection
userInterfaceStyle:userInterfaceStyle
preferredContentSizeCategory:sizeCategory
containerSize:windowSize];
#else
return [self traitCollectionWithHorizontalSizeClass:traitCollection.horizontalSizeClass
verticalSizeClass:traitCollection.verticalSizeClass
displayScale:traitCollection.displayScale
displayGamut:displayGamut
userInterfaceIdiom:traitCollection.userInterfaceIdiom
forceTouchCapability:traitCollection.forceTouchCapability
layoutDirection:layoutDirection
preferredContentSizeCategory:sizeCategory
containerSize:windowSize];
#endif
}
- (ASPrimitiveTraitCollection)primitiveTraitCollection
{
return (ASPrimitiveTraitCollection) {
.horizontalSizeClass = self.horizontalSizeClass,
.verticalSizeClass = self.verticalSizeClass,
.displayScale = self.displayScale,
.displayGamut = self.displayGamut,
.userInterfaceIdiom = self.userInterfaceIdiom,
.forceTouchCapability = self.forceTouchCapability,
.layoutDirection = self.layoutDirection,
#if TARGET_OS_TV
.userInterfaceStyle = self.userInterfaceStyle,
#endif
.preferredContentSizeCategory = ASPrimitiveContentSizeCategoryMake(self.preferredContentSizeCategory),
.containerSize = self.containerSize,
};
}
- (BOOL)isEqualToTraitCollection:(ASTraitCollection *)traitCollection
{
if (self == traitCollection) {
return YES;
}
return
self.horizontalSizeClass == traitCollection.horizontalSizeClass &&
self.verticalSizeClass == traitCollection.verticalSizeClass &&
self.displayScale == traitCollection.displayScale &&
self.displayGamut == traitCollection.displayGamut &&
self.userInterfaceIdiom == traitCollection.userInterfaceIdiom &&
self.forceTouchCapability == traitCollection.forceTouchCapability &&
self.layoutDirection == traitCollection.layoutDirection &&
#if TARGET_OS_TV
self.userInterfaceStyle == traitCollection.userInterfaceStyle &&
#endif
[self.preferredContentSizeCategory isEqualToString:traitCollection.preferredContentSizeCategory] &&
CGSizeEqualToSize(self.containerSize, traitCollection.containerSize);
}
@end