mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
added delegate method for video did finish, moved layer creation to after view displays, rearranged spinner logic, added tests
This commit is contained in:
@@ -7,25 +7,28 @@ typedef NS_ENUM(NSUInteger, ASVideoGravity) {
|
|||||||
ASVideoGravityResize
|
ASVideoGravityResize
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@protocol ASVideoNodeDelegate;
|
||||||
|
|
||||||
@interface ASVideoNode : ASControlNode<_ASDisplayLayerDelegate>
|
@interface ASVideoNode : ASControlNode<_ASDisplayLayerDelegate>
|
||||||
@property (atomic, strong, readwrite) AVAsset *asset;
|
@property (atomic, strong, readwrite) AVAsset *asset;
|
||||||
|
@property (atomic, strong, readonly) AVPlayer *player;
|
||||||
|
@property (atomic, strong, readonly) AVPlayerItem *currentItem;
|
||||||
@property (nonatomic, assign, readwrite) BOOL shouldAutoplay;
|
@property (nonatomic, assign, readwrite) BOOL shouldAutoplay;
|
||||||
@property (atomic) ASVideoGravity gravity;
|
@property (atomic) ASVideoGravity gravity;
|
||||||
@property (atomic) BOOL autorepeat;
|
@property (atomic) BOOL autorepeat;
|
||||||
@property (atomic) ASButtonNode *playButton;
|
@property (atomic) ASButtonNode *playButton;
|
||||||
@property (atomic) AVPlayer *player;
|
|
||||||
|
@property (atomic, weak, readwrite) id<ASVideoNodeDelegate> delegate;
|
||||||
|
|
||||||
- (void)play;
|
- (void)play;
|
||||||
- (void)pause;
|
- (void)pause;
|
||||||
|
|
||||||
|
- (BOOL)isPlaying;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@protocol ASVideoNodeDelegate <NSObject>
|
@protocol ASVideoNodeDelegate <NSObject>
|
||||||
|
@optional
|
||||||
|
- (void)videoDidReachEnd:(ASVideoNode *)videoNode;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@protocol ASVideoNodeDataSource <NSObject>
|
|
||||||
@optional
|
|
||||||
- (ASButtonNode *)playButtonForVideoNode:(ASVideoNode *)videoNode;
|
|
||||||
- (UIImage *)thumbnailForVideoNode:(ASVideoNode *) videoNode;
|
|
||||||
- (NSURL *)thumbnailURLForVideoNode:(ASVideoNode *)videoNode;
|
|
||||||
@end
|
|
||||||
|
|||||||
@@ -6,14 +6,18 @@
|
|||||||
{
|
{
|
||||||
ASDN::RecursiveMutex _lock;
|
ASDN::RecursiveMutex _lock;
|
||||||
|
|
||||||
__weak id<ASVideoNodeDataSource> _dataSource;
|
__weak id<ASVideoNodeDelegate> _delegate;
|
||||||
|
|
||||||
BOOL _shouldBePlaying;
|
BOOL _shouldBePlaying;
|
||||||
AVAsset *_asset;
|
AVAsset *_asset;
|
||||||
|
|
||||||
AVPlayerItem *_currentItem;
|
AVPlayerItem *_currentItem;
|
||||||
|
AVPlayer *_player;
|
||||||
|
|
||||||
ASButtonNode *_playButton;
|
ASButtonNode *_playButton;
|
||||||
ASDisplayNode *_playerNode;
|
ASDisplayNode *_playerNode;
|
||||||
ASDisplayNode *_spinner;
|
ASDisplayNode *_spinner;
|
||||||
|
ASVideoGravity _gravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -28,13 +32,6 @@
|
|||||||
{
|
{
|
||||||
if (!(self = [super init])) { return nil; }
|
if (!(self = [super init])) { return nil; }
|
||||||
|
|
||||||
_playerNode = [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
|
|
||||||
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
|
|
||||||
playerLayer.player = [[AVPlayer alloc] init];
|
|
||||||
return playerLayer;
|
|
||||||
}];
|
|
||||||
[self addSubnode:_playerNode];
|
|
||||||
|
|
||||||
self.gravity = ASVideoGravityResizeAspect;
|
self.gravity = ASVideoGravityResizeAspect;
|
||||||
|
|
||||||
[self addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
[self addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||||
@@ -51,12 +48,17 @@
|
|||||||
|
|
||||||
if (!(newState & ASInterfaceStateVisible)) {
|
if (!(newState & ASInterfaceStateVisible)) {
|
||||||
[self pause];
|
[self pause];
|
||||||
|
[(UIActivityIndicatorView *)_spinner.view stopAnimating];
|
||||||
[_spinner removeFromSupernode];
|
[_spinner removeFromSupernode];
|
||||||
} else {
|
} else {
|
||||||
if (_shouldBePlaying) {
|
if (_shouldBePlaying) {
|
||||||
[self play];
|
[self play];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newState & ASInterfaceStateVisible) {
|
||||||
|
[self displayDidFinish];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||||
@@ -76,7 +78,8 @@
|
|||||||
- (void)didPlayToEnd:(NSNotification *)notification
|
- (void)didPlayToEnd:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
if (ASObjectIsEqual([[notification object] asset], _asset)) {
|
if (ASObjectIsEqual([[notification object] asset], _asset)) {
|
||||||
[[((AVPlayerLayer *)_playerNode.layer) player] seekToTime:CMTimeMakeWithSeconds(0, 1)];
|
[_delegate videoDidReachEnd:self];
|
||||||
|
[_player seekToTime:CMTimeMakeWithSeconds(0, 1)];
|
||||||
|
|
||||||
if (_autorepeat) {
|
if (_autorepeat) {
|
||||||
[self play];
|
[self play];
|
||||||
@@ -90,6 +93,12 @@
|
|||||||
{
|
{
|
||||||
[super layout];
|
[super layout];
|
||||||
_playerNode.frame = self.bounds;
|
_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;
|
||||||
|
_playButton.hitTestSlop = UIEdgeInsetsMake(-verticalDiff, -horizontalDiff, -verticalDiff, -horizontalDiff);
|
||||||
|
|
||||||
|
_spinner.frame = _playButton.frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)tapped
|
- (void)tapped
|
||||||
@@ -123,18 +132,47 @@
|
|||||||
_currentItem = [[AVPlayerItem alloc] initWithAsset:_asset];
|
_currentItem = [[AVPlayerItem alloc] initWithAsset:_asset];
|
||||||
[_currentItem addObserver:self forKeyPath:NSStringFromSelector(@selector(status)) options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL];
|
[_currentItem addObserver:self forKeyPath:NSStringFromSelector(@selector(status)) options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL];
|
||||||
|
|
||||||
if (((AVPlayerLayer *)_playerNode.layer).player) {
|
if (_player) {
|
||||||
[((AVPlayerLayer *)_playerNode.layer).player replaceCurrentItemWithPlayerItem:_currentItem];
|
[_player replaceCurrentItemWithPlayerItem:_currentItem];
|
||||||
} else {
|
} else {
|
||||||
((AVPlayerLayer *)_playerNode.layer).player = [[AVPlayer alloc] initWithPlayerItem:_currentItem];
|
_player = [[AVPlayer alloc] initWithPlayerItem:_currentItem];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// 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) {
|
if (_shouldAutoplay) {
|
||||||
[self play];
|
[self play];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)videoGravity
|
||||||
|
{
|
||||||
|
if (_gravity == ASVideoGravityResize) {
|
||||||
|
return AVLayerVideoGravityResize;
|
||||||
|
}
|
||||||
|
if (_gravity == ASVideoGravityResizeAspectFill) {
|
||||||
|
return AVLayerVideoGravityResizeAspectFill;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AVLayerVideoGravityResizeAspect;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)clearFetchedData
|
- (void)clearFetchedData
|
||||||
{
|
{
|
||||||
[super clearFetchedData];
|
[super clearFetchedData];
|
||||||
@@ -142,10 +180,13 @@
|
|||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_lock);
|
ASDN::MutexLocker l(_lock);
|
||||||
((AVPlayerLayer *)_playerNode.layer).player = nil;
|
((AVPlayerLayer *)_playerNode.layer).player = nil;
|
||||||
|
_player = nil;
|
||||||
_shouldBePlaying = NO;
|
_shouldBePlaying = NO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Video Properties
|
||||||
|
|
||||||
- (void)setPlayButton:(ASButtonNode *)playButton
|
- (void)setPlayButton:(ASButtonNode *)playButton
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_lock);
|
ASDN::MutexLocker l(_lock);
|
||||||
@@ -174,6 +215,7 @@
|
|||||||
|
|
||||||
_asset = asset;
|
_asset = asset;
|
||||||
|
|
||||||
|
// FIXME: Adopt -setNeedsFetchData when it is available
|
||||||
if (self.interfaceState & ASInterfaceStateFetchData) {
|
if (self.interfaceState & ASInterfaceStateFetchData) {
|
||||||
[self fetchData];
|
[self fetchData];
|
||||||
}
|
}
|
||||||
@@ -185,6 +227,12 @@
|
|||||||
return _asset;
|
return _asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (AVPlayer *)player
|
||||||
|
{
|
||||||
|
ASDN::MutexLocker l(_lock);
|
||||||
|
return _player;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setGravity:(ASVideoGravity)gravity
|
- (void)setGravity:(ASVideoGravity)gravity
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_lock);
|
ASDN::MutexLocker l(_lock);
|
||||||
@@ -203,21 +251,18 @@
|
|||||||
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspect;
|
((AVPlayerLayer *)_playerNode.layer).videoGravity = AVLayerVideoGravityResizeAspect;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_gravity = gravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASVideoGravity)gravity
|
- (ASVideoGravity)gravity
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_lock);
|
ASDN::MutexLocker l(_lock);
|
||||||
|
|
||||||
if (ASObjectIsEqual(((AVPlayerLayer *)_playerNode.layer).contentsGravity, AVLayerVideoGravityResize)) {
|
return _gravity;
|
||||||
return ASVideoGravityResize;
|
|
||||||
}
|
|
||||||
if (ASObjectIsEqual(((AVPlayerLayer *)_playerNode.layer).contentsGravity, AVLayerVideoGravityResizeAspectFill)) {
|
|
||||||
return ASVideoGravityResizeAspectFill;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ASVideoGravityResizeAspect;
|
#pragma mark - Video Playback
|
||||||
}
|
|
||||||
|
|
||||||
- (void)play
|
- (void)play
|
||||||
{
|
{
|
||||||
@@ -225,55 +270,73 @@
|
|||||||
|
|
||||||
if (!_spinner) {
|
if (!_spinner) {
|
||||||
_spinner = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{
|
_spinner = [[ASDisplayNode alloc] initWithViewBlock:^UIView *{
|
||||||
UIActivityIndicatorView *spinnnerView = [[UIActivityIndicatorView alloc] initWithFrame:_playButton.frame];
|
UIActivityIndicatorView *spinnnerView = [[UIActivityIndicatorView alloc] init];
|
||||||
spinnnerView.color = [UIColor whiteColor];
|
spinnnerView.color = [UIColor whiteColor];
|
||||||
[spinnnerView startAnimating];
|
|
||||||
|
|
||||||
return spinnnerView;
|
return spinnnerView;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (![self ready]) {
|
[_player play];
|
||||||
[self addSubnode:_spinner];
|
|
||||||
}
|
|
||||||
|
|
||||||
[[((AVPlayerLayer *)_playerNode.layer) player] play];
|
|
||||||
_shouldBePlaying = YES;
|
_shouldBePlaying = YES;
|
||||||
_playButton.alpha = 0.0;
|
_playButton.alpha = 0.0;
|
||||||
// if ([self ready] && ![self.subnodes containsObject:_spinner]) {
|
|
||||||
// }
|
if (![self ready] && _shouldBePlaying && (self.interfaceState & ASInterfaceStateVisible)) {
|
||||||
|
[self addSubnode:_spinner];
|
||||||
|
[(UIActivityIndicatorView *)_spinner.view startAnimating];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)ready
|
- (BOOL)ready
|
||||||
{
|
{
|
||||||
return [((AVPlayerLayer *)_playerNode.layer) player].currentItem.status == AVPlayerItemStatusReadyToPlay;
|
return _currentItem.status == AVPlayerItemStatusReadyToPlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pause
|
- (void)pause
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_lock);
|
ASDN::MutexLocker l(_lock);
|
||||||
|
|
||||||
[[((AVPlayerLayer *)_playerNode.layer) player] pause];
|
[_player pause];
|
||||||
[((UIActivityIndicatorView *)_spinner.view) stopAnimating];
|
[((UIActivityIndicatorView *)_spinner.view) stopAnimating];
|
||||||
_shouldBePlaying = NO;
|
_shouldBePlaying = NO;
|
||||||
_playButton.alpha = 1.0;
|
_playButton.alpha = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (AVPlayerItem *)currentItem
|
- (BOOL)isPlaying
|
||||||
{
|
{
|
||||||
return _currentItem;
|
ASDN::MutexLocker l(_lock);
|
||||||
|
|
||||||
|
return (_player.rate > 0 && !_player.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Property Accessors for Tests
|
||||||
|
|
||||||
- (ASDisplayNode *)spinner
|
- (ASDisplayNode *)spinner
|
||||||
{
|
{
|
||||||
|
ASDN::MutexLocker l(_lock);
|
||||||
return _spinner;
|
return _spinner;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (AVPlayerItem *)curentItem
|
- (AVPlayerItem *)curentItem
|
||||||
{
|
{
|
||||||
|
ASDN::MutexLocker l(_lock);
|
||||||
return _currentItem;
|
return _currentItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (ASDisplayNode *)playerNode
|
||||||
|
{
|
||||||
|
ASDN::MutexLocker l(_lock);
|
||||||
|
return _playerNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)shouldBePlaying
|
||||||
|
{
|
||||||
|
ASDN::MutexLocker l(_lock);
|
||||||
|
return _shouldBePlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Lifecycle
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
|||||||
@@ -11,45 +11,51 @@
|
|||||||
#import "ASVideoNode.h"
|
#import "ASVideoNode.h"
|
||||||
|
|
||||||
@interface ASVideoNodeTests : XCTestCase
|
@interface ASVideoNodeTests : XCTestCase
|
||||||
|
{
|
||||||
|
ASVideoNode *_videoNode;
|
||||||
|
AVAsset *_firstAsset;
|
||||||
|
AVAsset *_secondAsset;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASVideoNode ()
|
@interface ASVideoNode ()
|
||||||
@property (atomic, readonly) AVPlayerItem *currentItem;
|
|
||||||
@property (atomic) ASInterfaceState interfaceState;
|
@property (atomic) ASInterfaceState interfaceState;
|
||||||
@property (atomic) ASDisplayNode *spinner;
|
@property (atomic) ASDisplayNode *spinner;
|
||||||
@end
|
@property (atomic) ASDisplayNode *playerNode;
|
||||||
|
@property (atomic) BOOL shouldBePlaying;
|
||||||
@interface AVPlayerItem ()
|
|
||||||
@property (nonatomic) AVPlayerItemStatus status;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ASVideoNodeTests
|
@implementation ASVideoNodeTests
|
||||||
|
|
||||||
|
- (void)setUp
|
||||||
|
{
|
||||||
|
_videoNode = [[ASVideoNode alloc] init];
|
||||||
|
_firstAsset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
|
||||||
|
_secondAsset = [AVAsset assetWithURL:[NSURL URLWithString:@"secondURL"]];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)testVideoNodeReplacesAVPlayerItemWhenNewURLIsSet
|
- (void)testVideoNodeReplacesAVPlayerItemWhenNewURLIsSet
|
||||||
{
|
{
|
||||||
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
|
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||||
videoNode.interfaceState = ASInterfaceStateFetchData;
|
_videoNode.asset = _firstAsset;
|
||||||
videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
|
|
||||||
|
|
||||||
AVPlayerItem *item = [videoNode currentItem];
|
AVPlayerItem *item = [_videoNode currentItem];
|
||||||
|
|
||||||
videoNode.asset = [AVAsset assetWithURL:[NSURL URLWithString:@"secondURL"]];
|
_videoNode.asset = _secondAsset;
|
||||||
AVPlayerItem *secondItem = [videoNode currentItem];
|
AVPlayerItem *secondItem = [_videoNode currentItem];
|
||||||
|
|
||||||
XCTAssertNotEqualObjects(item, secondItem);
|
XCTAssertNotEqualObjects(item, secondItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testVideoNodeDoesNotReplaceAVPlayerItemWhenSameURLIsSet
|
- (void)testVideoNodeDoesNotReplaceAVPlayerItemWhenSameURLIsSet
|
||||||
{
|
{
|
||||||
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
|
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||||
videoNode.interfaceState = ASInterfaceStateFetchData;
|
|
||||||
AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
|
|
||||||
|
|
||||||
videoNode.asset = asset;
|
_videoNode.asset = _firstAsset;
|
||||||
AVPlayerItem *item = [videoNode currentItem];
|
AVPlayerItem *item = [_videoNode currentItem];
|
||||||
|
|
||||||
videoNode.asset = asset;
|
_videoNode.asset = _firstAsset;
|
||||||
AVPlayerItem *secondItem = [videoNode currentItem];
|
AVPlayerItem *secondItem = [_videoNode currentItem];
|
||||||
|
|
||||||
XCTAssertEqualObjects(item, secondItem);
|
XCTAssertEqualObjects(item, secondItem);
|
||||||
}
|
}
|
||||||
@@ -58,53 +64,73 @@
|
|||||||
|
|
||||||
- (void)testSpinnerDefaultsToNil
|
- (void)testSpinnerDefaultsToNil
|
||||||
{
|
{
|
||||||
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
|
XCTAssertNil(_videoNode.spinner);
|
||||||
|
|
||||||
XCTAssertNil(videoNode.spinner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testOnPlayIfVideoIsNotReadyInitializeSpinnerAndAddAsSubnode
|
- (void)testOnPlayIfVideoIsNotReadyInitializeSpinnerAndAddAsSubnode
|
||||||
{
|
{
|
||||||
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
|
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||||
videoNode.interfaceState = ASInterfaceStateFetchData;
|
_videoNode.asset = _firstAsset;
|
||||||
AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
|
|
||||||
videoNode.asset = asset;
|
|
||||||
|
|
||||||
[videoNode play];
|
[_videoNode play];
|
||||||
|
|
||||||
XCTAssertNotNil(videoNode.spinner);
|
XCTAssertNotNil(_videoNode.spinner);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testOnPauseSpinnerIsPausedIfPresent
|
- (void)testOnPauseSpinnerIsPausedIfPresent
|
||||||
{
|
{
|
||||||
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
|
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||||
videoNode.interfaceState = ASInterfaceStateFetchData;
|
_videoNode.asset = _firstAsset;
|
||||||
AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
|
|
||||||
videoNode.asset = asset;
|
|
||||||
|
|
||||||
[videoNode play];
|
[_videoNode play];
|
||||||
|
|
||||||
[videoNode pause];
|
[_videoNode pause];
|
||||||
|
|
||||||
XCTAssertFalse(((UIActivityIndicatorView *)videoNode.spinner.view).isAnimating);
|
XCTAssertFalse(((UIActivityIndicatorView *)_videoNode.spinner.view).isAnimating);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testOnVideoReadySpinnerIsStoppedAndRemoved
|
- (void)testOnVideoReadySpinnerIsStoppedAndRemoved
|
||||||
{
|
{
|
||||||
ASVideoNode *videoNode = [[ASVideoNode alloc] init];
|
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||||
videoNode.interfaceState = ASInterfaceStateFetchData;
|
_videoNode.asset = _firstAsset;
|
||||||
AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
|
|
||||||
videoNode.asset = asset;
|
|
||||||
|
|
||||||
[videoNode play];
|
[_videoNode play];
|
||||||
[videoNode observeValueForKeyPath:@"status" ofObject:[videoNode currentItem] change:@{@"new" : @(AVPlayerItemStatusReadyToPlay)} context:NULL];
|
[_videoNode observeValueForKeyPath:@"status" ofObject:[_videoNode currentItem] change:@{@"new" : @(AVPlayerItemStatusReadyToPlay)} context:NULL];
|
||||||
|
|
||||||
XCTAssertFalse(((UIActivityIndicatorView *)videoNode.spinner.view).isAnimating);
|
XCTAssertFalse(((UIActivityIndicatorView *)_videoNode.spinner.view).isAnimating);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testPlayButtonUserInteractionIsNotEnabled
|
- (void)testPlayerDefaultsToNil
|
||||||
{
|
{
|
||||||
|
XCTAssertNil(_videoNode.player);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPlayerIsCreatedInFetchData
|
||||||
|
{
|
||||||
|
_videoNode.asset = _firstAsset;
|
||||||
|
|
||||||
|
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||||
|
|
||||||
|
XCTAssertNotNil(_videoNode.player);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testPlayerLayerNodeIsAddedOnDisplayDidFinish
|
||||||
|
{
|
||||||
|
_videoNode.asset = _firstAsset;
|
||||||
|
|
||||||
|
[_videoNode displayDidFinish];
|
||||||
|
|
||||||
|
XCTAssert([_videoNode.subnodes containsObject:_videoNode.playerNode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testVideoStartsPlayingOnDidDisplayIfAutoplayIsSet
|
||||||
|
{
|
||||||
|
_videoNode.asset = _firstAsset;
|
||||||
|
_videoNode.shouldAutoplay = YES;
|
||||||
|
|
||||||
|
[_videoNode displayDidFinish];
|
||||||
|
|
||||||
|
XCTAssertTrue(_videoNode.shouldBePlaying);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
10
examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
examples/ASCollectionView/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:Sample.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#import "ViewController.h"
|
#import "ViewController.h"
|
||||||
|
|
||||||
@interface ViewController()
|
@interface ViewController()<ASVideoNodeDelegate>
|
||||||
@property (nonatomic) ASVideoNode *videoNode;
|
@property (nonatomic) ASVideoNode *videoNode;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -51,6 +51,8 @@
|
|||||||
{
|
{
|
||||||
ASVideoNode *nicCageVideo = [[ASVideoNode alloc] init];
|
ASVideoNode *nicCageVideo = [[ASVideoNode alloc] init];
|
||||||
|
|
||||||
|
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:@"http://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.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);
|
||||||
@@ -102,4 +104,9 @@
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)videoDidReachEnd:(ASVideoNode *)videoNode
|
||||||
|
{
|
||||||
|
//Do something with your video if you so desire.
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
Reference in New Issue
Block a user