renamed nic cage sample, added redundancy for loading player in case its nil when visible, added video tests, disabled assert for new range controller

This commit is contained in:
Luke Parham
2016-01-14 02:39:36 -06:00
parent 579313f086
commit d9559111a0
26 changed files with 150 additions and 289 deletions

View File

@@ -9,13 +9,17 @@ typedef NS_ENUM(NSUInteger, ASVideoGravity) {
@protocol ASVideoNodeDelegate;
@interface ASVideoNode : ASControlNode<_ASDisplayLayerDelegate>
@interface ASVideoNode : ASControlNode
@property (atomic, strong, readwrite) AVAsset *asset;
@property (atomic, strong, readonly) AVPlayer *player;
@property (atomic, strong, readonly) AVPlayerItem *currentItem;
// When autoplay is set to true, a video node will play when it has both loaded and entered the "visible" interfaceState.
// If it leaves the visible interfaceState it will pause but will resume once it has returned
@property (nonatomic, assign, readwrite) BOOL shouldAutoplay;
@property (atomic) ASVideoGravity gravity;
@property (atomic) BOOL autorepeat;
@property (nonatomic, assign, readwrite) BOOL shouldAutorepeat;
@property (atomic) NSString *gravity;
@property (atomic) ASButtonNode *playButton;
@property (atomic, weak, readwrite) id<ASVideoNodeDelegate> delegate;
@@ -29,6 +33,6 @@ typedef NS_ENUM(NSUInteger, ASVideoGravity) {
@protocol ASVideoNodeDelegate <NSObject>
@optional
- (void)videoDidReachEnd:(ASVideoNode *)videoNode;
- (void)videoPlaybackDidFinish:(ASVideoNode *)videoNode;
@end

View File

@@ -1,6 +1,7 @@
#import "ASVideoNode.h"
#import "ASDisplayNode+Beta.h"
@interface ASVideoNode ()
{
@@ -9,6 +10,10 @@
__weak id<ASVideoNodeDelegate> _delegate;
BOOL _shouldBePlaying;
BOOL _shouldAutorepeat;
BOOL _shouldAutoplay;
AVAsset *_asset;
AVPlayerItem *_currentItem;
@@ -17,48 +22,44 @@
ASButtonNode *_playButton;
ASDisplayNode *_playerNode;
ASDisplayNode *_spinner;
ASVideoGravity _gravity;
NSString *_gravity;
}
@end
@interface ASDisplayNode ()
- (void)setInterfaceState:(ASInterfaceState)newState;
@end
@implementation ASVideoNode
- (instancetype)init
{
if (!(self = [super init])) { return nil; }
self.gravity = ASVideoGravityResizeAspect;
[ASDisplayNode setShouldUseNewRenderingRange:YES];
self.gravity = AVLayerVideoGravityResizeAspect;
[self addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
return self;
}
// FIXME: Adopt interfaceStateDidChange API
- (void)setInterfaceState:(ASInterfaceState)newState
- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState
{
[super setInterfaceState:newState];
if (!(newState & ASInterfaceStateVisible)) {
if (oldState & ASInterfaceStateVisible) {
if (_shouldBePlaying) {
[self pause];
_shouldBePlaying = YES;
} else {
[self pause];
}
[(UIActivityIndicatorView *)_spinner.view stopAnimating];
[_spinner removeFromSupernode];
}
} else {
if (_shouldBePlaying) {
[self play];
}
}
if (newState & ASInterfaceStateVisible) {
[self displayDidFinish];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
@@ -78,10 +79,12 @@
- (void)didPlayToEnd:(NSNotification *)notification
{
if (ASObjectIsEqual([[notification object] asset], _asset)) {
[_delegate videoDidReachEnd:self];
if ([_delegate respondsToSelector:@selector(videoPlaybackDidFinish:)]) {
[_delegate videoPlaybackDidFinish:self];
}
[_player seekToTime:CMTimeMakeWithSeconds(0, 1)];
if (_autorepeat) {
if (_shouldAutorepeat) {
[self play];
} else {
[self pause];
@@ -92,13 +95,35 @@
- (void)layout
{
[super layout];
_playerNode.frame = self.bounds;
CGFloat horizontalDiff = (self.bounds.size.width - _playButton.bounds.size.width)/2;
CGFloat verticalDiff = (self.bounds.size.height - _playButton.bounds.size.height)/2;
CGRect bounds = self.bounds;
_playerNode.frame = bounds;
_playerNode.layer.frame = bounds;
CGFloat horizontalDiff = (bounds.size.width - _playButton.bounds.size.width)/2;
CGFloat verticalDiff = (bounds.size.height - _playButton.bounds.size.height)/2;
_playButton.hitTestSlop = UIEdgeInsetsMake(-verticalDiff, -horizontalDiff, -verticalDiff, -horizontalDiff);
_spinner.frame = _playButton.frame;
_spinner.bounds = CGRectMake(0, 0, 44, 44);
_spinner.position = CGPointMake(bounds.size.width/2, bounds.size.height/2);
}
- (void)didLoad
{
[super didLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
_playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
if (!_player) {
_player = [AVPlayer playerWithPlayerItem:[[AVPlayerItem alloc] initWithAsset:_asset]];
}
playerLayer.player = _player;
playerLayer.videoGravity = [self gravity];
return playerLayer;
}];
[self insertSubnode:_playerNode atIndex:0];
}
- (void)tapped
@@ -140,38 +165,6 @@
}
}
// FIXME: Adopt interfaceStateDidChange API
- (void)displayDidFinish
{
[super displayDidFinish];
ASDN::MutexLocker l(_lock);
_playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
playerLayer.player = _player;
playerLayer.videoGravity = [self videoGravity];
return playerLayer;
}];
[self insertSubnode:_playerNode atIndex:0];
if (_shouldAutoplay) {
[self play];
}
}
- (NSString *)videoGravity
{
if (_gravity == ASVideoGravityResize) {
return AVLayerVideoGravityResize;
}
if (_gravity == ASVideoGravityResizeAspectFill) {
return AVLayerVideoGravityResizeAspectFill;
}
return AVLayerVideoGravityResizeAspect;
}
- (void)clearFetchedData
{
@@ -181,7 +174,27 @@
ASDN::MutexLocker l(_lock);
((AVPlayerLayer *)_playerNode.layer).player = nil;
_player = nil;
_shouldBePlaying = NO;
}
}
- (void)visibilityDidChange:(BOOL)isVisible
{
ASDN::MutexLocker l(_lock);
if (_shouldAutoplay && _playerNode.isNodeLoaded) {
[self play];
}
if (isVisible) {
if (_playerNode.isNodeLoaded) {
if (!_player) {
_player = [AVPlayer playerWithPlayerItem:[[AVPlayerItem alloc] initWithAsset:_asset]];
}
((AVPlayerLayer *)_playerNode.layer).player = _player;
}
if (_shouldBePlaying) {
[self play];
}
}
}
@@ -233,29 +246,16 @@
return _player;
}
- (void)setGravity:(ASVideoGravity)gravity
- (void)setGravity:(NSString *)gravity
{
ASDN::MutexLocker l(_lock);
switch (gravity) {
case ASVideoGravityResize:
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResize;
break;
case ASVideoGravityResizeAspect:
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspect;
break;
case ASVideoGravityResizeAspectFill:
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspectFill;
break;
default:
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspect;
break;
if (_playerNode.isNodeLoaded) {
((AVPlayerLayer *)_playerNode.layer).videoGravity = gravity;
}
_gravity = gravity;
}
- (ASVideoGravity)gravity
- (NSString *)gravity
{
ASDN::MutexLocker l(_lock);
@@ -323,6 +323,12 @@
return _currentItem;
}
- (void)setCurrentItem:(AVPlayerItem *)currentItem
{
ASDN::MutexLocker l(_lock);
_currentItem = currentItem;
}
- (ASDisplayNode *)playerNode
{
ASDN::MutexLocker l(_lock);
@@ -339,7 +345,7 @@
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
@try {
[_currentItem removeObserver:self forKeyPath:NSStringFromSelector(@selector(status))];
}

View File

@@ -64,7 +64,7 @@
[node enterInterfaceState:ASInterfaceStateDisplay];
ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled");
// ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled");
if ([ASDisplayNode shouldUseNewRenderingRange]) {
[node recursivelyEnsureDisplaySynchronously:NO];
} else {
@@ -102,7 +102,7 @@
// The node calls clearCurrentContents and suspends display
[node exitInterfaceState:ASInterfaceStateDisplay];
ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled");
// ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled");
if ([ASDisplayNode shouldUseNewRenderingRange]) {
if (![node isLayerBacked]) {

View File

@@ -18,11 +18,24 @@
}
@end
@interface ASVideoNode ()
@interface ASVideoNode () {
ASDisplayNode *_playerNode;
}
@property (atomic) ASInterfaceState interfaceState;
@property (atomic) ASDisplayNode *spinner;
@property (atomic) ASDisplayNode *playerNode;
@property (atomic) BOOL shouldBePlaying;
- (void)setPlayerNode:(ASDisplayNode *)playerNode;
@end
@implementation ASVideoNode (Test)
- (void)setPlayerNode:(ASDisplayNode *)playerNode
{
_playerNode = playerNode;
}
@end
@implementation ASVideoNodeTests
@@ -114,21 +127,48 @@
XCTAssertNotNil(_videoNode.player);
}
- (void)testPlayerLayerNodeIsAddedOnDisplayDidFinish
- (void)testPlayerLayerNodeIsAddedOnDidLoad
{
_videoNode.asset = _firstAsset;
[_videoNode displayDidFinish];
[_videoNode didLoad];
XCTAssert([_videoNode.subnodes containsObject:_videoNode.playerNode]);
}
- (void)testVideoStartsPlayingOnDidDisplayIfAutoplayIsSet
- (void)testVideoStartsPlayingOnDidDidBecomeVisibleWhenShouldAutoplay
{
_videoNode.asset = _firstAsset;
_videoNode.shouldAutoplay = YES;
_videoNode.playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
return playerLayer;
}];
_videoNode.playerNode.layer.frame = CGRectZero;
[_videoNode displayDidFinish];
[_videoNode visibilityDidChange:YES];
XCTAssertTrue(_videoNode.shouldBePlaying);
}
- (void)testVideoShouldPauseWhenItLeavesVisibleButShouldKnowPlayingShouldRestartLater
{
_videoNode.asset = _firstAsset;
[_videoNode play];
[_videoNode interfaceStateDidChange:ASInterfaceStateNone fromState:ASInterfaceStateVisible];
XCTAssertFalse(_videoNode.isPlaying);
XCTAssertTrue(_videoNode.shouldBePlaying);
}
- (void)testVideoThatIsPlayingWhenItLeavesVisibleRangeStartsAgainWhenItComesBack
{
_videoNode.asset = _firstAsset;
[_videoNode play];
[_videoNode interfaceStateDidChange:ASInterfaceStateVisible fromState:ASInterfaceStateNone];
[_videoNode interfaceStateDidChange:ASInterfaceStateNone fromState:ASInterfaceStateVisible];
XCTAssertTrue(_videoNode.shouldBePlaying);
}

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -14,6 +14,7 @@
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
#import <AsyncDisplayKit/ASStackLayoutSpec.h>
#import <AsyncDisplayKit/ASInsetLayoutSpec.h>
#import <AsyncDisplayKit/ASVideoNode.h>
@@ -22,7 +23,6 @@ static const CGFloat kImageSize = 80.0f;
static const CGFloat kOuterPadding = 16.0f;
static const CGFloat kInnerPadding = 10.0f;
@interface NicCageNode ()
{
CGSize _kittenSize;
@@ -82,8 +82,9 @@ static const CGFloat kInnerPadding = 10.0f;
_kittenSize = size;
_videoNode = [[ASVideoNode alloc] init];
// _videoNode.shouldAutoplay = YES;
_videoNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor();
_videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"http://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-753fe655-86bb-46da-89b7-aa59c60e49c0-niccage.mp4"]];
_videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"https://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-753fe655-86bb-46da-89b7-aa59c60e49c0-niccage.mp4"]];
[self addSubnode:_videoNode];

View File

@@ -16,7 +16,7 @@
#import "BlurbNode.h"
#import "NicCageNode.h"
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
static const NSInteger kCageSize = 20; // intial number of Cage cells in ASTableView
static const NSInteger kCageBatchSize = 10; // number of Cage cells to add to ASTableView
@@ -38,7 +38,6 @@ static const NSInteger kMaxCageSize = 100; // max number of Cage cells al
@end
@implementation ViewController
#pragma mark -
@@ -109,7 +108,6 @@ static const NSInteger kMaxCageSize = 100; // max number of Cage cells al
[_tableView setEditing:!_tableView.editing animated:YES];
}
#pragma mark -
#pragma mark ASTableView.

View File

@@ -14,7 +14,6 @@
3EC0CDCBA10D483D9F386E5E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D24B17D1E4A4E7A9566C5E9 /* libPods.a */; };
6C2C82AC19EE274300767484 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AA19EE274300767484 /* Default-667h@2x.png */; };
6C2C82AD19EE274300767484 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AB19EE274300767484 /* Default-736h@3x.png */; };
ACC945AE1BA9EFBA005E1FB8 /* ScreenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AD1BA9EFBA005E1FB8 /* ScreenNode.m */; };
AE8E41191C228A4A00913AC4 /* bearacrat@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = AE8E41181C228A4A00913AC4 /* bearacrat@2x.jpg */; };
AE8E411B1C23634C00913AC4 /* simon.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = AE8E411A1C235A6000913AC4 /* simon.mp4 */; };
AED850671C22679200183ED3 /* playButton@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AED850661C22679200183ED3 /* playButton@2x.png */; };
@@ -34,8 +33,6 @@
3D24B17D1E4A4E7A9566C5E9 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
6C2C82AA19EE274300767484 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = SOURCE_ROOT; };
6C2C82AB19EE274300767484 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = SOURCE_ROOT; };
ACC945AC1BA9EFB3005E1FB8 /* ScreenNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScreenNode.h; sourceTree = "<group>"; };
ACC945AD1BA9EFBA005E1FB8 /* ScreenNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenNode.m; sourceTree = "<group>"; };
AE8E41181C228A4A00913AC4 /* bearacrat@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "bearacrat@2x.jpg"; sourceTree = "<group>"; };
AE8E411A1C235A6000913AC4 /* simon.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = simon.mp4; sourceTree = "<group>"; };
AED850661C22679200183ED3 /* playButton@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "playButton@2x.png"; sourceTree = "<group>"; };
@@ -87,8 +84,6 @@
05E2128919D4DB510098F589 /* AppDelegate.m */,
05E2128B19D4DB510098F589 /* ViewController.h */,
05E2128C19D4DB510098F589 /* ViewController.m */,
ACC945AC1BA9EFB3005E1FB8 /* ScreenNode.h */,
ACC945AD1BA9EFBA005E1FB8 /* ScreenNode.m */,
05E2128419D4DB510098F589 /* Supporting Files */,
);
path = Sample;
@@ -251,7 +246,6 @@
05E2128D19D4DB510098F589 /* ViewController.m in Sources */,
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */,
05E2128719D4DB510098F589 /* main.m in Sources */,
ACC945AE1BA9EFBA005E1FB8 /* ScreenNode.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -1,19 +0,0 @@
//
// ScreenNode.h
// Sample
//
// Created by Huy Nguyen on 16/09/15.
// Copyright (c) 2015 Facebook. All rights reserved.
//
#import <AsyncDisplayKit/AsyncDisplayKit.h>
@interface ScreenNode : ASDisplayNode
@property (nonatomic, strong) ASMultiplexImageNode *imageNode;
@property (nonatomic, strong) ASButtonNode *buttonNode;
- (void)start;
- (void)reload;
@end

View File

@@ -1,158 +0,0 @@
//
// ScreenNode.m
// Sample
//
// Created by Huy Nguyen on 16/09/15.
// Copyright (c) 2015 Facebook. All rights reserved.
//
#import "ScreenNode.h"
@interface ScreenNode() <ASMultiplexImageNodeDataSource, ASMultiplexImageNodeDelegate, ASImageDownloaderProtocol>
@end
@implementation ScreenNode
- (instancetype)init
{
if (!(self = [super init])) {
return nil;
}
// multiplex image node!
// NB: we're using a custom downloader with an artificial delay for this demo, but ASBasicImageDownloader works too!
_imageNode = [[ASMultiplexImageNode alloc] initWithCache:nil downloader:self];
_imageNode.dataSource = self;
_imageNode.delegate = self;
// placeholder colour
_imageNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor();
// load low-quality images before high-quality images
_imageNode.downloadsIntermediateImages = YES;
// simple status label. Synchronous to avoid flicker / placeholder state when updating.
_buttonNode = [[ASButtonNode alloc] init];
[_buttonNode addTarget:self action:@selector(reload) forControlEvents:ASControlNodeEventTouchUpInside];
_buttonNode.titleNode.displaysAsynchronously = NO;
[self addSubnode:_imageNode];
[self addSubnode:_buttonNode];
return self;
}
- (void)start
{
[self setText:@"loading…"];
_buttonNode.userInteractionEnabled = NO;
_imageNode.imageIdentifiers = @[ @"best", @"medium", @"worst" ]; // go!
}
- (void)reload
{
[self start];
[_imageNode reloadImageIdentifierSources];
}
- (void)setText:(NSString *)text
{
NSDictionary *attributes = @{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:22.0f]};
NSAttributedString *string = [[NSAttributedString alloc] initWithString:text
attributes:attributes];
[_buttonNode setAttributedTitle:string forState:ASButtonStateNormal];
[self setNeedsLayout];
}
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
ASRatioLayoutSpec *imagePlaceholder = [ASRatioLayoutSpec ratioLayoutSpecWithRatio:1 child:_imageNode];
ASStackLayoutSpec *verticalStack = [[ASStackLayoutSpec alloc] init];
verticalStack.direction = ASStackLayoutDirectionVertical;
verticalStack.spacing = 10;
verticalStack.justifyContent = ASStackLayoutJustifyContentCenter;
verticalStack.alignItems = ASStackLayoutAlignItemsCenter;
verticalStack.children = @[imagePlaceholder, _buttonNode];
return [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(10, 10, 10, 10) child:verticalStack];
}
#pragma mark -
#pragma mark ASMultiplexImageNode data source & delegate.
- (NSURL *)multiplexImageNode:(ASMultiplexImageNode *)imageNode URLForImageIdentifier:(id)imageIdentifier
{
if ([imageIdentifier isEqualToString:@"worst"]) {
return [NSURL URLWithString:@"https://raw.githubusercontent.com/facebook/AsyncDisplayKit/master/examples/Multiplex/worst.png"];
}
if ([imageIdentifier isEqualToString:@"medium"]) {
return [NSURL URLWithString:@"https://raw.githubusercontent.com/facebook/AsyncDisplayKit/master/examples/Multiplex/medium.png"];
}
if ([imageIdentifier isEqualToString:@"best"]) {
return [NSURL URLWithString:@"https://raw.githubusercontent.com/facebook/AsyncDisplayKit/master/examples/Multiplex/best.png"];
}
// unexpected identifier
return nil;
}
- (void)multiplexImageNode:(ASMultiplexImageNode *)imageNode didFinishDownloadingImageWithIdentifier:(id)imageIdentifier error:(NSError *)error
{
[self setText:[NSString stringWithFormat:@"loaded '%@'", imageIdentifier]];
if ([imageIdentifier isEqualToString:@"best"]) {
[self setText:[_buttonNode.titleNode.attributedString.string stringByAppendingString:@". tap to reload"]];
_buttonNode.userInteractionEnabled = YES;
}
}
#pragma mark -
#pragma mark ASImageDownloaderProtocol.
- (id)downloadImageWithURL:(NSURL *)URL
callbackQueue:(dispatch_queue_t)callbackQueue
downloadProgressBlock:(void (^)(CGFloat progress))downloadProgressBlock
completion:(void (^)(CGImageRef image, NSError *error))completion
{
// if no callback queue is supplied, run on the main thread
if (callbackQueue == nil) {
callbackQueue = dispatch_get_main_queue();
}
// call completion blocks
void (^handler)(NSURLResponse *, NSData *, NSError *) = ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// add an artificial delay
usleep(1.0 * USEC_PER_SEC);
// ASMultiplexImageNode callbacks
dispatch_async(callbackQueue, ^{
if (downloadProgressBlock) {
downloadProgressBlock(1.0f);
}
if (completion) {
completion([[UIImage imageWithData:data] CGImage], connectionError);
}
});
};
// let NSURLConnection do the heavy lifting
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[NSURLConnection sendAsynchronousRequest:request
queue:[[NSOperationQueue alloc] init]
completionHandler:handler];
// return nil, don't support cancellation
return nil;
}
- (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier
{
// no-op, don't support cancellation
}
@end

View File

@@ -39,7 +39,7 @@
videoNode.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3);
videoNode.gravity = ASVideoGravityResizeAspectFill;
videoNode.gravity = AVLayerVideoGravityResizeAspectFill;
videoNode.backgroundColor = [UIColor lightGrayColor];
@@ -53,14 +53,14 @@
nicCageVideo.delegate = self;
nicCageVideo.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"http://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-753fe655-86bb-46da-89b7-aa59c60e49c0-niccage.mp4"]];
nicCageVideo.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"https://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-753fe655-86bb-46da-89b7-aa59c60e49c0-niccage.mp4"]];
nicCageVideo.frame = CGRectMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3, [UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/3);
nicCageVideo.gravity = ASVideoGravityResize;
nicCageVideo.gravity = AVLayerVideoGravityResize;
nicCageVideo.backgroundColor = [UIColor lightGrayColor];
nicCageVideo.autorepeat = YES;
nicCageVideo.shouldAutorepeat = YES;
nicCageVideo.playButton = [self playButton];
return nicCageVideo;
@@ -78,7 +78,7 @@
simonVideo.gravity = ASVideoGravityResizeAspect;
simonVideo.backgroundColor = [UIColor lightGrayColor];
simonVideo.autorepeat = YES;
simonVideo.shouldAutorepeat = YES;
simonVideo.playButton = [self playButton];
simonVideo.shouldAutoplay = YES;
@@ -90,11 +90,11 @@
ASButtonNode *playButton = [[ASButtonNode alloc] init];
UIImage *image = [UIImage imageNamed:@"playButton@2x.png"];
[playButton setImage:image forState:ASButtonStateNormal];
[playButton setImage:image forState:ASControlStateNormal];
[playButton measure:CGSizeMake(50, 50)];
playButton.bounds = CGRectMake(0, 0, playButton.calculatedSize.width, playButton.calculatedSize.height);
playButton.position = CGPointMake([UIScreen mainScreen].bounds.size.width/4, ([UIScreen mainScreen].bounds.size.height/3)/2);
[playButton setImage:[UIImage imageNamed:@"playButtonSelected@2x.png"] forState:ASButtonStateHighlighted];
[playButton setImage:[UIImage imageNamed:@"playButtonSelected@2x.png"] forState:ASControlStateHighlighted];
return playButton;
}
@@ -104,9 +104,4 @@
return YES;
}
- (void)videoDidReachEnd:(ASVideoNode *)videoNode
{
//Do something with your video if you so desire.
}
@end