Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tvOS] Fixes errors when building against tvOS SDK #728

Merged
merged 31 commits into from
Mar 11, 2018
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7e8c3e2
[tvOS] Fixes errors when building against tvOS SDK
alexhillc Dec 26, 2017
bd9fd57
Update CHANGELOG.md
alexhillc Dec 26, 2017
8663491
Merge branch 'master' of github.com:TextureGroup/Texture into tvos
alexhillc Dec 26, 2017
46f5412
[tvOS] Fixes implicit conversion between UIViewAnimationCurve +
alexhillc Dec 26, 2017
6b90382
Enable tvOS deployment target in Texture.podspec (for CI)
alexhillc Dec 27, 2017
b1b582a
[ASMultiplexImageNode] Fixes typo
alexhillc Dec 28, 2017
7759cf7
[tvOS] Fixes warnings related to @available guards in Xcode 9
alexhillc Dec 28, 2017
8dbcc51
[ASAvailability] Update AS_AVAILABLE_XXX fallbacks to function more like
alexhillc Dec 28, 2017
6607bda
[ASControlNode] Adds missing 'super' call in -[ASControlNode didLoad]
alexhillc Dec 28, 2017
14a8e91
Fix API_AVAILABLE iOS requirement
alexhillc Dec 29, 2017
bcdae3f
[ASDisplayNode] Fixes last of the linker warnings related to category
alexhillc Dec 30, 2017
9673a83
[NSParagraphStyle+ASText] Fixes typo related to testing
alexhillc Dec 30, 2017
bf9aa78
[ASControlNode] Re-add helpful comment
alexhillc Dec 30, 2017
8eb2dbe
[ASTextKitCoreTextAdditions] Adds mappings for kCTParagraphStyleSpeci…
alexhillc Jan 6, 2018
cb0e735
Merge remote-tracking branch 'upstream/master' into tvos
alexhillc Jan 13, 2018
3da014a
[AsyncDisplayKit] Update project file to include new/deleted files
alexhillc Jan 13, 2018
fdf22d6
[ASControlNode+tvOS] Add missing Foundation import (whoops!)
alexhillc Jan 13, 2018
2d6d0a7
Update podspec to only link AssetsLibrary framework on iOS
alexhillc Jan 13, 2018
c7462f6
[ASTextKitCoreTextAdditions] If kCTParagraphStyleAttributeName key-value
alexhillc Jan 16, 2018
12a06b3
Merge remote-tracking branch 'upstream/master' into tvos
alexhillc Jan 16, 2018
91dcb20
[ASMultiplexImageNode] Bump availability check to support < Xcode 9
alexhillc Jan 16, 2018
ef16069
Merge branch 'master' into tvos
alexhillc Jan 16, 2018
305b443
[ASTraitCollection] Fixes typo that was causing build to fail
alexhillc Jan 16, 2018
2ec4233
Merge remote-tracking branch 'upstream/master' into tvos
alexhillc Jan 21, 2018
fd246ad
Merge branch 'master' into tvos
appleguy Feb 9, 2018
1f76d48
Merge branch 'tvos' of github.com:alexhillc/Texture into tvos
alexhillc Feb 9, 2018
b9cb2fa
Merge branch 'master' into tvos
appleguy Feb 19, 2018
917d3f3
Merge branch 'tvos' of github.com:alexhillc/Texture into tvos
alexhillc Feb 21, 2018
ebbf512
Clean up formatting to adhere to character/line limit + braces
alexhillc Feb 24, 2018
1a5b195
Merge branch 'master' into tvos
alexhillc Feb 28, 2018
873933e
Merge branch 'master' into tvos
alexhillc Mar 3, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## master
* Add your own contributions to the next release on the line below this with your name.
- [tvOS] Fixes errors when building against tvOS SDK [Alex Hill](https://github.com/alexhillc) [#728](https://github.com/TextureGroup/Texture/pull/728)
- [ASRectMap] Replace implementation of ASRectTable with a simpler one based on unordered_map.[Scott Goodson](https://github.com/appleguy) [#719](https://github.com/TextureGroup/Texture/pull/719)
- [ASCollectionView] Add missing flags for ASCollectionDelegate [Ilya Zheleznikov](https://github.com/ilyailya) [#718](https://github.com/TextureGroup/Texture/pull/718)
- [ASNetworkImageNode] Deprecates .URLs in favor of .URL [Garrett Moon](https://github.com/garrettmoon) [#699](https://github.com/TextureGroup/Texture/pull/699)
Expand Down
4 changes: 2 additions & 2 deletions Source/ASCollectionView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ - (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionV
// Experiments done by Instagram show that this option being YES (default)
// when unused causes a significant hit to scroll performance.
// https://github.com/Instagram/IGListKit/issues/318
if (AS_AVAILABLE_IOS(10)) {
if (AS_AVAILABLE_IOS_TVOS(10, 10)) {
super.prefetchingEnabled = NO;
}

Expand Down Expand Up @@ -1974,7 +1974,7 @@ - (ASRangeController *)rangeController
/// The UIKit version of this method is only available on iOS >= 9
- (NSArray<NSIndexPath *> *)asdk_indexPathsForVisibleSupplementaryElementsOfKind:(NSString *)kind
{
if (AS_AVAILABLE_IOS(9)) {
if (AS_AVAILABLE_IOS_TVOS(9, 9)) {
return [self indexPathsForVisibleSupplementaryElementsOfKind:kind];
}

Expand Down
7 changes: 6 additions & 1 deletion Source/ASControlNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,17 @@ static UIControlState const ASControlStateSelected ASDISPLAYNODE_DEPRECATED_MSG(
@param event The event which triggered these control actions. May be nil.
*/
- (void)sendActionsForControlEvents:(ASControlNodeEvent)controlEvents withEvent:(nullable UIEvent *)event;
@end

#if TARGET_OS_TV
@interface ASControlNode (tvOS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding categories, this is a nice improvement for organization.


/**
@abstract How the node looks when it isn't focused. Exposed here so that subclasses can override.
*/
- (void)setDefaultFocusAppearance;
#endif

@end
#endif

NS_ASSUME_NONNULL_END
5 changes: 4 additions & 1 deletion Source/ASControlNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//

#import <AsyncDisplayKit/ASControlNode.h>
#import <AsyncDisplayKit/ASControlNode+Private.h>
#import <AsyncDisplayKit/ASControlNode+Subclasses.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASImageNode.h>
Expand Down Expand Up @@ -103,10 +104,12 @@ - (instancetype)init
#if TARGET_OS_TV
- (void)didLoad
{
[super didLoad];

// On tvOS all controls, such as buttons, interact with the focus system even if they don't have a target set on them.
// Here we add our own internal tap gesture to handle this behaviour.
self.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGestureRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pressDown)];
UITapGestureRecognizer *tapGestureRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_pressDown)];
tapGestureRec.allowedPressTypes = @[@(UIPressTypeSelect)];
[self.view addGestureRecognizer:tapGestureRec];
}
Expand Down
34 changes: 0 additions & 34 deletions Source/ASDisplayNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3469,40 +3469,6 @@ - (void)asyncTraitCollectionDidChange
{
// Subclass override
}

#if TARGET_OS_TV
#pragma mark - UIFocusEnvironment Protocol (tvOS)

- (void)setNeedsFocusUpdate
{

}

- (void)updateFocusIfNeeded
{

}

- (BOOL)shouldUpdateFocusInContext:(UIFocusUpdateContext *)context
{
return NO;
}

- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{

}

- (UIView *)preferredFocusedView
{
if (self.nodeLoaded) {
return self.view;
} else {
return nil;
}
}
#endif

@end

#pragma mark - ASDisplayNode (Debugging)
Expand Down
2 changes: 1 addition & 1 deletion Source/ASImageNode+AnimatedImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ - (void)displayLinkFired:(CADisplayLink *)displayLink
CFTimeInterval timeBetweenLastFire;
if (self.lastDisplayLinkFire == 0) {
timeBetweenLastFire = 0;
} else if (AS_AVAILABLE_IOS(10)){
} else if (AS_AVAILABLE_IOS_TVOS(10, 10)) {
timeBetweenLastFire = displayLink.targetTimestamp - displayLink.timestamp;
} else {
timeBetweenLastFire = CACurrentMediaTime() - self.lastDisplayLinkFire;
Expand Down
5 changes: 5 additions & 0 deletions Source/ASImageNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ typedef UIImage * _Nullable (^asimagenode_modification_block_t)(UIImage *image);

@end

#if TARGET_OS_TV
@interface ASImageNode (tvOS)
@end
#endif

@interface ASImageNode (AnimatedImage)

/**
Expand Down
14 changes: 4 additions & 10 deletions Source/ASMultiplexImageNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,12 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) {
*/
@property (nonatomic, assign, readwrite) BOOL shouldRenderProgressImages;

#if TARGET_OS_IOS
/**
* @abstract The image manager that this image node should use when requesting images from the Photos framework. If this is `nil` (the default), then `PHImageManager.defaultManager` is used.

* @see `+[NSURL URLWithAssetLocalIdentifier:targetSize:contentMode:options:]` below.
*/
@property (nullable, nonatomic, strong) PHImageManager *imageManager;
#endif
@property (nullable, nonatomic, strong) PHImageManager *imageManager API_AVAILABLE(ios(8.0), tvos(10.0));
@end


Expand Down Expand Up @@ -245,7 +243,6 @@ didFinishDownloadingImageWithIdentifier:(ASImageIdentifier)imageIdentifier
*/
- (nullable NSURL *)multiplexImageNode:(ASMultiplexImageNode *)imageNode URLForImageIdentifier:(ASImageIdentifier)imageIdentifier;

#if TARGET_OS_IOS
/**
* @abstract A PHAsset for the specific asset local identifier
* @param imageNode The sender.
Expand All @@ -256,12 +253,10 @@ didFinishDownloadingImageWithIdentifier:(ASImageIdentifier)imageIdentifier
* @note This method may be called from any thread.
* @return A PHAsset corresponding to `assetLocalIdentifier`, or nil if none is available.
*/
- (nullable PHAsset *)multiplexImageNode:(ASMultiplexImageNode *)imageNode assetForLocalIdentifier:(NSString *)assetLocalIdentifier;
#endif
- (nullable PHAsset *)multiplexImageNode:(ASMultiplexImageNode *)imageNode assetForLocalIdentifier:(NSString *)assetLocalIdentifier API_AVAILABLE(ios(8.0), tvos(10.0));
@end

#pragma mark -
#if TARGET_OS_IOS
#pragma mark -
@interface NSURL (ASPhotosFrameworkURLs)

/**
Expand All @@ -275,9 +270,8 @@ didFinishDownloadingImageWithIdentifier:(ASImageIdentifier)imageIdentifier
+ (NSURL *)URLWithAssetLocalIdentifier:(NSString *)assetLocalIdentifier
targetSize:(CGSize)targetSize
contentMode:(PHImageContentMode)contentMode
options:(PHImageRequestOptions *)options AS_WARN_UNUSED_RESULT;
options:(PHImageRequestOptions *)options AS_WARN_UNUSED_RESULT API_AVAILABLE(ios(8.0), tvos(10.0));

@end
#endif

NS_ASSUME_NONNULL_END
100 changes: 55 additions & 45 deletions Source/ASMultiplexImageNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
//

#import <AsyncDisplayKit/ASMultiplexImageNode.h>

#if TARGET_OS_IOS
#import <AssetsLibrary/AssetsLibrary.h>
#endif

#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkSubclasses.h>
Expand Down Expand Up @@ -136,15 +139,16 @@ - (void)_fetchImageWithIdentifierFromCache:(id)imageIdentifier URL:(NSURL *)imag
@param completionBlock The block to be performed when the image has been loaded, if possible. May not be nil.
*/
- (void)_loadALAssetWithIdentifier:(id)imageIdentifier URL:(NSURL *)assetURL completion:(void (^)(UIImage *image, NSError *error))completionBlock;
#endif

/**
@abstract Loads the image corresponding to the given image request from the Photos framework.
@param imageIdentifier The identifier for the image to be loaded. May not be nil.
@param request The photos image request to load. May not be nil.
@param completionBlock The block to be performed when the image has been loaded, if possible. May not be nil.
*/
- (void)_loadPHAssetWithRequest:(ASPhotosFrameworkImageRequest *)request identifier:(id)imageIdentifier completion:(void (^)(UIImage *image, NSError *error))completionBlock;
#endif
- (void)_loadPHAssetWithRequest:(ASPhotosFrameworkImageRequest *)request identifier:(id)imageIdentifier completion:(void (^)(UIImage *image, NSError *error))completionBlock API_AVAILABLE(ios(8.0), tvos(10.0));

/**
@abstract Downloads the image corresponding to the given imageIdentifier from the given URL.
@param imageIdentifier The identifier for the image to be downloaded. May not be nil.
Expand Down Expand Up @@ -345,9 +349,9 @@ - (void)setDataSource:(id <ASMultiplexImageNodeDataSource>)dataSource
_dataSource = dataSource;
_dataSourceFlags.image = [_dataSource respondsToSelector:@selector(multiplexImageNode:imageForImageIdentifier:)];
_dataSourceFlags.URL = [_dataSource respondsToSelector:@selector(multiplexImageNode:URLForImageIdentifier:)];
#if TARGET_OS_IOS
_dataSourceFlags.asset = [_dataSource respondsToSelector:@selector(multiplexImageNode:assetForLocalIdentifier:)];
#endif
if (AS_AVAILABLE_IOS_TVOS(8, 10)) {
_dataSourceFlags.asset = [_dataSource respondsToSelector:@selector(multiplexImageNode:assetForLocalIdentifier:)];
}
}


Expand Down Expand Up @@ -616,56 +620,62 @@ - (void)_loadNextImage
return;
}

#if TARGET_OS_IOS
#if TARGET_OS_IOS
// If it's an assets-library URL, we need to fetch it from the assets library.
if ([[nextImageURL scheme] isEqualToString:kAssetsLibraryURLScheme]) {
// Load the asset.
[self _loadALAssetWithIdentifier:nextImageIdentifier URL:nextImageURL completion:^(UIImage *downloadedImage, NSError *error) {
as_log_verbose(ASImageLoadingLog(), "Acquired image from assets library for %@ %@", weakSelf, nextImageIdentifier);
finishedLoadingBlock(downloadedImage, nextImageIdentifier, error);
}];

return;
}
// Likewise, if it's a iOS 8 Photo asset, we need to fetch it accordingly.
else if (ASPhotosFrameworkImageRequest *request = [ASPhotosFrameworkImageRequest requestWithURL:nextImageURL]) {
[self _loadPHAssetWithRequest:request identifier:nextImageIdentifier completion:^(UIImage *image, NSError *error) {
as_log_verbose(ASImageLoadingLog(), "Acquired image from Photos for %@ %@", weakSelf, nextImageIdentifier);
finishedLoadingBlock(image, nextImageIdentifier, error);
}];
#endif

if (AS_AVAILABLE_IOS_TVOS(8, 10)) {
// Likewise, if it's a iOS 8 Photo asset, we need to fetch it accordingly.
if (ASPhotosFrameworkImageRequest *request = [ASPhotosFrameworkImageRequest requestWithURL:nextImageURL]) {
[self _loadPHAssetWithRequest:request identifier:nextImageIdentifier completion:^(UIImage *image, NSError *error) {
as_log_verbose(ASImageLoadingLog(), "Acquired image from Photos for %@ %@", weakSelf, nextImageIdentifier);
finishedLoadingBlock(image, nextImageIdentifier, error);
}];

return;
}
}
#endif
else // Otherwise, it's a web URL that we can download.
{
// First, check the cache.
[self _fetchImageWithIdentifierFromCache:nextImageIdentifier URL:nextImageURL completion:^(UIImage *imageFromCache) {

// Otherwise, it's a web URL that we can download.
// First, check the cache.
[self _fetchImageWithIdentifierFromCache:nextImageIdentifier URL:nextImageURL completion:^(UIImage *imageFromCache) {
__typeof__(self) strongSelf = weakSelf;
if (!strongSelf)
return;

// If we had a cache-hit, we're done.
if (imageFromCache) {
as_log_verbose(ASImageLoadingLog(), "Acquired image from cache for %@ id: %@ img: %@", strongSelf, nextImageIdentifier, imageFromCache);
finishedLoadingBlock(imageFromCache, nextImageIdentifier, nil);
return;
}

// If the next image to load has changed, bail.
if (!ASObjectIsEqual([strongSelf _nextImageIdentifierToDownload], nextImageIdentifier)) {
finishedLoadingBlock(nil, nil, [NSError errorWithDomain:ASMultiplexImageNodeErrorDomain code:ASMultiplexImageNodeErrorCodeBestImageIdentifierChanged userInfo:nil]);
return;
}

// Otherwise, we've got to download it.
[strongSelf _downloadImageWithIdentifier:nextImageIdentifier URL:nextImageURL completion:^(UIImage *downloadedImage, NSError *error) {
__typeof__(self) strongSelf = weakSelf;
if (!strongSelf)
return;

// If we had a cache-hit, we're done.
if (imageFromCache) {
as_log_verbose(ASImageLoadingLog(), "Acquired image from cache for %@ id: %@ img: %@", strongSelf, nextImageIdentifier, imageFromCache);
finishedLoadingBlock(imageFromCache, nextImageIdentifier, nil);
return;
}

// If the next image to load has changed, bail.
if (!ASObjectIsEqual([strongSelf _nextImageIdentifierToDownload], nextImageIdentifier)) {
finishedLoadingBlock(nil, nil, [NSError errorWithDomain:ASMultiplexImageNodeErrorDomain code:ASMultiplexImageNodeErrorCodeBestImageIdentifierChanged userInfo:nil]);
return;
if (downloadedImage) {
as_log_verbose(ASImageLoadingLog(), "Acquired image from download for %@ id: %@ img: %@", strongSelf, nextImageIdentifier, downloadedImage);
} else {
as_log_error(ASImageLoadingLog(), "Error downloading image for %@ id: %@ err: %@", strongSelf, nextImageIdentifier, error);
}

// Otherwise, we've got to download it.
[strongSelf _downloadImageWithIdentifier:nextImageIdentifier URL:nextImageURL completion:^(UIImage *downloadedImage, NSError *error) {
__typeof__(self) strongSelf = weakSelf;
if (downloadedImage) {
as_log_verbose(ASImageLoadingLog(), "Acquired image from download for %@ id: %@ img: %@", strongSelf, nextImageIdentifier, downloadedImage);
} else {
as_log_error(ASImageLoadingLog(), "Error downloading image for %@ id: %@ err: %@", strongSelf, nextImageIdentifier, error);
}
finishedLoadingBlock(downloadedImage, nextImageIdentifier, error);
}];
finishedLoadingBlock(downloadedImage, nextImageIdentifier, error);
}];
}
}];
}
#if TARGET_OS_IOS
- (void)_loadALAssetWithIdentifier:(id)imageIdentifier URL:(NSURL *)assetURL completion:(void (^)(UIImage *image, NSError *error))completionBlock
Expand All @@ -686,7 +696,7 @@ - (void)_loadALAssetWithIdentifier:(id)imageIdentifier URL:(NSURL *)assetURL com
completionBlock(nil, error);
}];
}

#endif
- (void)_loadPHAssetWithRequest:(ASPhotosFrameworkImageRequest *)request identifier:(id)imageIdentifier completion:(void (^)(UIImage *image, NSError *error))completionBlock
{
ASDisplayNodeAssertNotNil(imageIdentifier, @"imageIdentifier is required");
Expand Down Expand Up @@ -774,7 +784,7 @@ - (void)_loadPHAssetWithRequest:(ASPhotosFrameworkImageRequest *)request identif
_phImageRequestOperation = newImageRequestOp;
[phImageRequestQueue addOperation:newImageRequestOp];
}
#endif

- (void)_fetchImageWithIdentifierFromCache:(id)imageIdentifier URL:(NSURL *)imageURL completion:(void (^)(UIImage *image))completionBlock
{
ASDisplayNodeAssertNotNil(imageIdentifier, @"imageIdentifier is required");
Expand Down
8 changes: 7 additions & 1 deletion Source/ASTableView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ - (void)setElement:(ASCollectionElement *)element
self.backgroundColor = node.backgroundColor;
self.selectionStyle = node.selectionStyle;
self.selectedBackgroundView = node.selectedBackgroundView;
#if TARGET_OS_IOS
self.separatorInset = node.separatorInset;
self.selectionStyle = node.selectionStyle;
#endif
self.accessoryType = node.accessoryType;

// the following ensures that we clip the entire cell to it's bounds if node.clipsToBounds is set (the default)
Expand Down Expand Up @@ -927,6 +928,7 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa
ASCellNode *node = [_dataController.visibleMap elementForItemAtIndexPath:indexPath].node;
CGFloat height = node.calculatedSize.height;

#if TARGET_OS_IOS
/**
* Weirdly enough, Apple expects the return value here to _include_ the height
* of the separator, if there is one! So if our node wants to be 43.5, we need
Expand All @@ -936,6 +938,8 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa
if (tableView.separatorStyle != UITableViewCellSeparatorStyleNone) {
height += 1.0 / ASScreenScale();
}
#endif

return height;
}

Expand Down Expand Up @@ -1777,13 +1781,15 @@ - (BOOL)dataController:(ASDataController *)dataController presentedSizeForElemen
}
CGRect rect = [self rectForRowAtIndexPath:indexPath];

#if TARGET_OS_IOS
/**
* Weirdly enough, Apple expects the return value in tableView:heightForRowAtIndexPath: to _include_ the height
* of the separator, if there is one! So if rectForRow would return 44.0 we need to use 43.5.
*/
if (self.separatorStyle != UITableViewCellSeparatorStyleNone) {
rect.size.height -= 1.0 / ASScreenScale();
}
#endif

return (fabs(rect.size.height - size.height) < FLT_EPSILON);
}
Expand Down
8 changes: 6 additions & 2 deletions Source/Base/ASAvailability.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@

// Use __builtin_available if we're on Xcode >= 9, AS_AT_LEAST otherwise.
#if __has_builtin(__builtin_available)
#define AS_AVAILABLE_IOS(ver) __builtin_available(iOS ver, *)
#define AS_AVAILABLE_IOS(ver) __builtin_available(iOS ver, *)
#define AS_AVAILABLE_TVOS(ver) __builtin_available(tvOS ver, *)
#define AS_AVAILABLE_IOS_TVOS(ver1, ver2) __builtin_available(iOS ver1, tvOS ver2, *)
#else
#define AS_AVAILABLE_IOS(ver) AS_AT_LEAST_IOS##ver
#define AS_AVAILABLE_IOS(ver) (TARGET_OS_IOS && AS_AT_LEAST_IOS##ver)
#define AS_AVAILABLE_TVOS(ver) (TARGET_OS_TV && AS_AT_LEAST_IOS##ver)
#define AS_AVAILABLE_IOS_TVOS(ver1, ver2) (AS_AVAILABLE_IOS(ver1) || AS_AVAILABLE_TVOS(ver2))
#endif

// If Yoga is available, make it available anywhere we use ASAvailability.
Expand Down
Loading