mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-03-28 23:58:50 +08:00
Merge remote-tracking branch
# Conflicts: # AsyncDisplayKit/ASVideoNode.mm
This commit is contained in:
19
.editorconfig
Normal file
19
.editorconfig
Normal file
@@ -0,0 +1,19 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[**.{h,cc,mm,m}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{md,markdown}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Makefiles always use tabs for indentation
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
@@ -5,7 +5,7 @@ Pod::Spec.new do |spec|
|
||||
spec.homepage = 'http://asyncdisplaykit.org'
|
||||
spec.authors = { 'Scott Goodson' => 'scottgoodson@gmail.com', 'Ryan Nystrom' => 'rnystrom@fb.com' }
|
||||
spec.summary = 'Smooth asynchronous user interfaces for iOS apps.'
|
||||
spec.source = { :git => 'https://github.com/facebook/AsyncDisplayKit.git', :tag => '1.9.7.3' }
|
||||
spec.source = { :git => 'https://github.com/facebook/AsyncDisplayKit.git', :tag => '1.9.73' }
|
||||
|
||||
spec.documentation_url = 'http://asyncdisplaykit.org/appledoc/'
|
||||
|
||||
@@ -69,5 +69,6 @@ Pod::Spec.new do |spec|
|
||||
}
|
||||
|
||||
spec.ios.deployment_target = '7.0'
|
||||
spec.tvos.deployment_target = '9.0'
|
||||
# Uncomment when fixed: The platform of the target `Pods` (tvOS 9.0) is not compatible with `PINRemoteImage/iOS (2.1.4)`, which does not support `tvos`.) during validation
|
||||
# spec.tvos.deployment_target = '9.0'
|
||||
end
|
||||
|
||||
@@ -122,10 +122,14 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
|
||||
_URL = URL;
|
||||
|
||||
if (reset || _URL == nil) {
|
||||
BOOL hasURL = _URL == nil;
|
||||
if (reset || hasURL) {
|
||||
self.image = _defaultImage;
|
||||
ASPerformBlockOnMainThread(^{
|
||||
self.currentImageQuality = 1.0;
|
||||
/* We want to maintain the order that currentImageQuality is set regardless of the calling thread,
|
||||
so always use a dispatch_async to ensure that we queue the operations in the correct order.
|
||||
(see comment in displayDidFinish) */
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.currentImageQuality = hasURL ? 0.0 : 1.0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -151,8 +155,12 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
_defaultImage = defaultImage;
|
||||
|
||||
if (!_imageLoaded) {
|
||||
ASPerformBlockOnMainThread(^{
|
||||
self.currentImageQuality = 0.0;
|
||||
BOOL hasURL = _URL == nil;
|
||||
/* We want to maintain the order that currentImageQuality is set regardless of the calling thread,
|
||||
so always use a dispatch_async to ensure that we queue the operations in the correct order.
|
||||
(see comment in displayDidFinish) */
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.currentImageQuality = hasURL ? 0.0 : 1.0;
|
||||
});
|
||||
_lock.unlock();
|
||||
// Locking: it is important to release _lock before entering setImage:, as it needs to release the lock before -invalidateCalculatedLayout.
|
||||
@@ -229,7 +237,9 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
if (result) {
|
||||
self.image = result;
|
||||
_imageLoaded = YES;
|
||||
_currentImageQuality = 1.0;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
_currentImageQuality = 1.0;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,7 +332,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
return;
|
||||
}
|
||||
strongSelf.image = progressImage;
|
||||
ASPerformBlockOnMainThread(^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
strongSelf->_currentImageQuality = progress;
|
||||
});
|
||||
};
|
||||
@@ -347,7 +357,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
self.animatedImage = nil;
|
||||
self.image = _defaultImage;
|
||||
_imageLoaded = NO;
|
||||
ASPerformBlockOnMainThread(^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.currentImageQuality = 0.0;
|
||||
});
|
||||
}
|
||||
@@ -431,9 +441,14 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_imageLoaded = YES;
|
||||
self.currentImageQuality = 1.0;
|
||||
/* We want to maintain the order that currentImageQuality is set regardless of the calling thread,
|
||||
so always use a dispatch_async to ensure that we queue the operations in the correct order.
|
||||
(see comment in displayDidFinish) */
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.currentImageQuality = 1.0;
|
||||
});
|
||||
[_delegate imageNode:self didLoadImage:self.image];
|
||||
});
|
||||
}
|
||||
@@ -459,7 +474,9 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
} else {
|
||||
strongSelf.image = [imageContainer asdk_image];
|
||||
}
|
||||
strongSelf->_currentImageQuality = 1.0;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
strongSelf->_currentImageQuality = 1.0;
|
||||
});
|
||||
}
|
||||
|
||||
strongSelf->_downloadIdentifier = nil;
|
||||
|
||||
@@ -101,7 +101,7 @@ static NSString * const kStatus = @"status";
|
||||
- (ASDisplayNode *)constructPlayerNode
|
||||
{
|
||||
ASVideoNode * __weak weakSelf = self;
|
||||
|
||||
|
||||
return [[ASDisplayNode alloc] initWithLayerBlock:^CALayer *{
|
||||
AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
|
||||
playerLayer.player = weakSelf.player;
|
||||
@@ -113,16 +113,47 @@ static NSString * const kStatus = @"status";
|
||||
- (AVPlayerItem *)constructPlayerItem
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
|
||||
if (_asset != nil) {
|
||||
if ([_asset isKindOfClass:[AVURLAsset class]]) {
|
||||
return [[AVPlayerItem alloc] initWithURL:((AVURLAsset *)_asset).URL];
|
||||
} else {
|
||||
return [[AVPlayerItem alloc] initWithAsset:_asset];
|
||||
return [[AVPlayerItem alloc] initWithAsset:_asset];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)prepareToPlayAsset:(AVAsset *)asset withKeys:(NSArray<NSString *> *)requestedKeys
|
||||
{
|
||||
for (NSString *key in requestedKeys) {
|
||||
NSError *error = nil;
|
||||
AVKeyValueStatus keyStatus = [asset statusOfValueForKey:key error:&error];
|
||||
if (keyStatus == AVKeyValueStatusFailed) {
|
||||
NSLog(@"Asset loading failed with error: %@", error);
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
||||
if (![asset isPlayable]) {
|
||||
NSLog(@"Asset is not playable.");
|
||||
return;
|
||||
}
|
||||
|
||||
AVPlayerItem *playerItem = [self constructPlayerItem];
|
||||
[self setCurrentItem:playerItem];
|
||||
|
||||
if (_player != nil) {
|
||||
[_player replaceCurrentItemWithPlayerItem:playerItem];
|
||||
} else {
|
||||
self.player = [AVPlayer playerWithPlayerItem:playerItem];
|
||||
}
|
||||
|
||||
if (_placeholderImageNode.image == nil) {
|
||||
[self generatePlaceholderImage];
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
_timeObserverInterval = CMTimeMake(1, _periodicTimeObserverTimescale);
|
||||
_timeObserver = [_player addPeriodicTimeObserverForInterval:_timeObserverInterval queue:NULL usingBlock:^(CMTime time){
|
||||
[weakSelf periodicTimeObserver:time];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)addPlayerItemObservers:(AVPlayerItem *)playerItem
|
||||
@@ -130,7 +161,7 @@ static NSString * const kStatus = @"status";
|
||||
[playerItem addObserver:self forKeyPath:kStatus options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:ASVideoNodeContext];
|
||||
[playerItem addObserver:self forKeyPath:kPlaybackLikelyToKeepUpKey options:NSKeyValueObservingOptionNew context:ASVideoNodeContext];
|
||||
[playerItem addObserver:self forKeyPath:kplaybackBufferEmpty options:NSKeyValueObservingOptionNew context:ASVideoNodeContext];
|
||||
|
||||
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self selector:@selector(didPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
|
||||
[notificationCenter addObserver:self selector:@selector(errorWhilePlaying:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
|
||||
@@ -147,7 +178,7 @@ static NSString * const kStatus = @"status";
|
||||
@catch (NSException * __unused exception) {
|
||||
NSLog(@"Unnecessary KVO removal");
|
||||
}
|
||||
|
||||
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
|
||||
[notificationCenter removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
|
||||
@@ -178,7 +209,7 @@ static NSString * const kStatus = @"status";
|
||||
{
|
||||
ASVideoNode * __weak weakSelf = self;
|
||||
AVAsset * __weak asset = self.asset;
|
||||
|
||||
|
||||
[self imageAtTime:kCMTimeZero completionHandler:^(UIImage *image) {
|
||||
ASPerformBlockOnMainThread(^{
|
||||
// Ensure the asset hasn't changed since the image request was made
|
||||
@@ -193,17 +224,17 @@ static NSString * const kStatus = @"status";
|
||||
{
|
||||
ASPerformBlockOnBackgroundThread(^{
|
||||
AVAsset *asset = self.asset;
|
||||
|
||||
|
||||
// Skip the asset image generation if we don't have any tracks available that are capable of supporting it
|
||||
NSArray<AVAssetTrack *>* visualAssetArray = [asset tracksWithMediaCharacteristic:AVMediaCharacteristicVisual];
|
||||
if (visualAssetArray.count == 0) {
|
||||
completionHandler(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
AVAssetImageGenerator *previewImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
|
||||
previewImageGenerator.appliesPreferredTrackTransform = YES;
|
||||
|
||||
|
||||
[previewImageGenerator generateCGImagesAsynchronouslyForTimes:@[[NSValue valueWithCMTime:imageTime]]
|
||||
completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
|
||||
if (error != nil && result != AVAssetImageGeneratorCancelled) {
|
||||
@@ -217,18 +248,18 @@ static NSString * const kStatus = @"status";
|
||||
- (void)setVideoPlaceholderImage:(UIImage *)image
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
|
||||
if (_placeholderImageNode == nil && image != nil) {
|
||||
_placeholderImageNode = [[ASImageNode alloc] init];
|
||||
_placeholderImageNode.layerBacked = YES;
|
||||
_placeholderImageNode.contentMode = ASContentModeFromVideoGravity(_gravity);
|
||||
}
|
||||
|
||||
|
||||
_placeholderImageNode.image = image;
|
||||
|
||||
|
||||
ASPerformBlockOnMainThread(^{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
|
||||
if (_placeholderImageNode != nil) {
|
||||
[self insertSubnode:_placeholderImageNode atIndex:0];
|
||||
[self setNeedsLayout];
|
||||
@@ -239,11 +270,11 @@ static NSString * const kStatus = @"status";
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
|
||||
if (object != _currentPlayerItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ([keyPath isEqualToString:kStatus]) {
|
||||
if ([change[NSKeyValueChangeNewKey] integerValue] == AVPlayerItemStatusReadyToPlay) {
|
||||
[self removeSpinner];
|
||||
@@ -285,26 +316,14 @@ static NSString * const kStatus = @"status";
|
||||
[super fetchData];
|
||||
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
AVPlayerItem *playerItem = [self constructPlayerItem];
|
||||
self.currentItem = playerItem;
|
||||
|
||||
if (_player != nil) {
|
||||
[_player replaceCurrentItemWithPlayerItem:playerItem];
|
||||
} else {
|
||||
self.player = [AVPlayer playerWithPlayerItem:playerItem];
|
||||
}
|
||||
|
||||
if (_placeholderImageNode.image == nil) {
|
||||
[self generatePlaceholderImage];
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
_timeObserverInterval = CMTimeMake(1, _periodicTimeObserverTimescale);
|
||||
_timeObserver = [_player addPeriodicTimeObserverForInterval:_timeObserverInterval queue:NULL usingBlock:^(CMTime time){
|
||||
[weakSelf periodicTimeObserver:time];
|
||||
}];
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
AVAsset *asset = self.asset;
|
||||
NSArray<NSString *> *requestedKeys = @[ @"playable" ];
|
||||
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{
|
||||
ASPerformBlockOnMainThread(^{
|
||||
[self prepareToPlayAsset:asset withKeys:requestedKeys];
|
||||
});
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,11 +344,11 @@ static NSString * const kStatus = @"status";
|
||||
[super clearFetchedData];
|
||||
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
self.player = nil;
|
||||
self.currentItem = nil;
|
||||
_placeholderImageNode.image = nil;
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
self.player = nil;
|
||||
self.currentItem = nil;
|
||||
_placeholderImageNode.image = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,10 +391,10 @@ static NSString * const kStatus = @"status";
|
||||
- (void)setPlayButton:(ASButtonNode *)playButton
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
|
||||
[_playButton removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside];
|
||||
[_playButton removeFromSupernode];
|
||||
|
||||
|
||||
_playButton = playButton;
|
||||
|
||||
[self addSubnode:playButton];
|
||||
@@ -397,13 +416,13 @@ static NSString * const kStatus = @"status";
|
||||
if (ASAssetIsEqual(asset, _asset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
[self clearFetchedData];
|
||||
|
||||
|
||||
_asset = asset;
|
||||
|
||||
|
||||
[self setNeedsDataFetch];
|
||||
|
||||
|
||||
if (_shouldAutoplay) {
|
||||
[self play];
|
||||
}
|
||||
@@ -480,14 +499,14 @@ static NSString * const kStatus = @"status";
|
||||
if(![self isStateChangeValid:ASVideoNodePlayerStatePlaying]){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_player == nil) {
|
||||
[self setNeedsDataFetch];
|
||||
}
|
||||
|
||||
|
||||
if (_playerNode == nil) {
|
||||
_playerNode = [self constructPlayerNode];
|
||||
|
||||
|
||||
if (_playButton.supernode == self) {
|
||||
[self insertSubnode:_playerNode belowSubnode:_playButton];
|
||||
} else {
|
||||
@@ -585,7 +604,7 @@ static NSString * const kStatus = @"status";
|
||||
[_delegate videoPlaybackDidFinish:self];
|
||||
}
|
||||
[_player seekToTime:kCMTimeZero];
|
||||
|
||||
|
||||
if (_shouldAutorepeat) {
|
||||
[self play];
|
||||
} else {
|
||||
@@ -633,11 +652,11 @@ static NSString * const kStatus = @"status";
|
||||
- (void)setCurrentItem:(AVPlayerItem *)currentItem
|
||||
{
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
|
||||
[self removePlayerItemObservers:_currentPlayerItem];
|
||||
|
||||
|
||||
_currentPlayerItem = currentItem;
|
||||
|
||||
|
||||
[self addPlayerItemObservers:currentItem];
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
@@ -17,6 +19,7 @@
|
||||
AVURLAsset *_firstAsset;
|
||||
AVAsset *_secondAsset;
|
||||
NSURL *_url;
|
||||
NSArray *_requestedKeys;
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -32,6 +35,7 @@
|
||||
@property (atomic, readwrite) BOOL shouldBePlaying;
|
||||
|
||||
- (void)setVideoPlaceholderImage:(UIImage *)image;
|
||||
- (void)prepareToPlayAsset:(AVAsset *)asset withKeys:(NSArray *)requestedKeys;
|
||||
|
||||
@end
|
||||
|
||||
@@ -43,6 +47,7 @@
|
||||
_firstAsset = [AVURLAsset assetWithURL:[NSURL URLWithString:@"firstURL"]];
|
||||
_secondAsset = [AVAsset assetWithURL:[NSURL URLWithString:@"secondURL"]];
|
||||
_url = [NSURL URLWithString:@"testURL"];
|
||||
_requestedKeys = @[ @"playable" ];
|
||||
}
|
||||
|
||||
|
||||
@@ -131,23 +136,42 @@
|
||||
XCTAssertNil(_videoNode.player);
|
||||
}
|
||||
|
||||
- (void)testPlayerIsCreatedInFetchData
|
||||
- (void)testPlayerIsCreatedAsynchronouslyInFetchData
|
||||
{
|
||||
_videoNode.asset = _firstAsset;
|
||||
AVAsset *asset = _firstAsset;
|
||||
|
||||
id assetMock = [OCMockObject partialMockForObject:asset];
|
||||
id videoNodeMock = [OCMockObject partialMockForObject:_videoNode];
|
||||
|
||||
[[[assetMock stub] andReturnValue:@YES] isPlayable];
|
||||
[[[videoNodeMock expect] andForwardToRealObject] prepareToPlayAsset:assetMock withKeys:_requestedKeys];
|
||||
|
||||
_videoNode.asset = assetMock;
|
||||
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||
|
||||
[videoNodeMock verifyWithDelay:1.0f];
|
||||
|
||||
XCTAssertNotNil(_videoNode.player);
|
||||
}
|
||||
|
||||
- (void)testPlayerIsCreatedInFetchDataWithURL
|
||||
- (void)testPlayerIsCreatedAsynchronouslyInFetchDataWithURL
|
||||
{
|
||||
_videoNode.asset = [AVAsset assetWithURL:_url];
|
||||
AVAsset *asset = [AVAsset assetWithURL:_url];
|
||||
|
||||
id assetMock = [OCMockObject partialMockForObject:asset];
|
||||
id videoNodeMock = [OCMockObject partialMockForObject:_videoNode];
|
||||
|
||||
[[[assetMock stub] andReturnValue:@YES] isPlayable];
|
||||
[[[videoNodeMock expect] andForwardToRealObject] prepareToPlayAsset:assetMock withKeys:_requestedKeys];
|
||||
|
||||
_videoNode.asset = assetMock;
|
||||
_videoNode.interfaceState = ASInterfaceStateFetchData;
|
||||
|
||||
[videoNodeMock verifyWithDelay:1.0f];
|
||||
|
||||
XCTAssertNotNil(_videoNode.player);
|
||||
}
|
||||
|
||||
|
||||
- (void)testPlayerLayerNodeIsAddedOnDidLoadIfVisibleAndAutoPlaying
|
||||
{
|
||||
_videoNode.asset = _firstAsset;
|
||||
@@ -284,13 +308,17 @@
|
||||
|
||||
- (void)testVideoThatDoesNotAutorepeatsShouldPauseOnPlaybackEnd
|
||||
{
|
||||
_videoNode.asset = _firstAsset;
|
||||
id assetMock = [OCMockObject partialMockForObject:_firstAsset];
|
||||
[[[assetMock stub] andReturnValue:@YES] isPlayable];
|
||||
|
||||
_videoNode.asset = assetMock;
|
||||
_videoNode.shouldAutorepeat = NO;
|
||||
|
||||
[_videoNode didLoad];
|
||||
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStateFetchData];
|
||||
[_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys];
|
||||
[_videoNode play];
|
||||
|
||||
|
||||
XCTAssertTrue(_videoNode.isPlaying);
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:AVPlayerItemDidPlayToEndTimeNotification object:_videoNode.currentItem];
|
||||
@@ -301,11 +329,15 @@
|
||||
|
||||
- (void)testVideoThatAutorepeatsShouldRepeatOnPlaybackEnd
|
||||
{
|
||||
_videoNode.asset = _firstAsset;
|
||||
id assetMock = [OCMockObject partialMockForObject:_firstAsset];
|
||||
[[[assetMock stub] andReturnValue:@YES] isPlayable];
|
||||
|
||||
_videoNode.asset = assetMock;
|
||||
_videoNode.shouldAutorepeat = YES;
|
||||
|
||||
[_videoNode didLoad];
|
||||
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStateFetchData];
|
||||
[_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys];
|
||||
[_videoNode play];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:AVPlayerItemDidPlayToEndTimeNotification object:_videoNode.currentItem];
|
||||
@@ -315,9 +347,13 @@
|
||||
|
||||
- (void)testVideoResumedWhenBufferIsLikelyToKeepUp
|
||||
{
|
||||
_videoNode.asset = _firstAsset;
|
||||
id assetMock = [OCMockObject partialMockForObject:_firstAsset];
|
||||
[[[assetMock stub] andReturnValue:@YES] isPlayable];
|
||||
|
||||
_videoNode.asset = assetMock;
|
||||
|
||||
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStateFetchData];
|
||||
[_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys];
|
||||
[_videoNode pause];
|
||||
_videoNode.shouldBePlaying = YES;
|
||||
|
||||
@@ -372,9 +408,20 @@
|
||||
|
||||
- (void)testClearingFetchedContentShouldClearAssetData
|
||||
{
|
||||
_videoNode.asset = _firstAsset;
|
||||
AVAsset *asset = _firstAsset;
|
||||
|
||||
id assetMock = [OCMockObject partialMockForObject:asset];
|
||||
id videoNodeMock = [OCMockObject partialMockForObject:_videoNode];
|
||||
|
||||
[[[assetMock stub] andReturnValue:@YES] isPlayable];
|
||||
[[[videoNodeMock expect] andForwardToRealObject] prepareToPlayAsset:assetMock withKeys:_requestedKeys];
|
||||
|
||||
_videoNode.asset = assetMock;
|
||||
[_videoNode fetchData];
|
||||
[_videoNode setVideoPlaceholderImage:[[UIImage alloc] init]];
|
||||
|
||||
[videoNodeMock verifyWithDelay:1.0f];
|
||||
|
||||
XCTAssertNotNil(_videoNode.player);
|
||||
XCTAssertNotNil(_videoNode.currentItem);
|
||||
XCTAssertNotNil(_videoNode.placeholderImageNode.image);
|
||||
|
||||
Reference in New Issue
Block a user