#import #import "MLWAsyncAVPlayer.h" @implementation MLWAsyncAVPlayer - (instancetype)init { self = [super init]; if (self) { [self setValue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL) forKeyPath:@"_player.stateDispatchQueue"]; } return self; } // Move completions from following methods to main thread - (void)prerollAtRate:(float)rate completionHandler:(void (^)(BOOL))completionHandler { [super prerollAtRate:rate completionHandler:^(BOOL finished) { dispatch_sync(dispatch_get_main_queue(), ^{ completionHandler(finished); }); }]; } - (id)addBoundaryTimeObserverForTimes:(NSArray *)times queue:(dispatch_queue_t)queue usingBlock:(void (^)(void))block { return [super addBoundaryTimeObserverForTimes:times queue:queue usingBlock:^{ dispatch_sync(dispatch_get_main_queue(), ^{ block(); }); }]; } - (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(dispatch_queue_t)queue usingBlock:(void (^)(CMTime))block { return [super addPeriodicTimeObserverForInterval:interval queue:queue usingBlock:^(CMTime time) { dispatch_sync(dispatch_get_main_queue(), ^{ block(time); }); }]; } // Move KVO of player properties to main thread - (void)willChangeValueForKey:(NSString *)key { if ([NSThread isMainThread]) { [super willChangeValueForKey:key]; return; } dispatch_sync(dispatch_get_main_queue(), ^{ [super willChangeValueForKey:key]; }); } - (void)didChangeValueForKey:(NSString *)key { if ([NSThread isMainThread]) { [super didChangeValueForKey:key]; return; } dispatch_sync(dispatch_get_main_queue(), ^{ [super didChangeValueForKey:key]; }); } @end // @implementation AVPlayerItem (MLWAsync) + (void)load { [self jr_swizzleMethod:@selector(willChangeValueForKey:) withMethod:@selector(mlw_willChangeValueForKey:) error:nil]; [self jr_swizzleMethod:@selector(didChangeValueForKey:) withMethod:@selector(mlw_didChangeValueForKey:) error:nil]; } - (void)mlw_willChangeValueForKey:(NSString *)key { if ([NSThread isMainThread]) { [self mlw_willChangeValueForKey:key]; return; } dispatch_sync(dispatch_get_main_queue(), ^{ [self mlw_willChangeValueForKey:key]; }); } - (void)mlw_didChangeValueForKey:(NSString *)key { if ([NSThread isMainThread]) { [self mlw_didChangeValueForKey:key]; return; } dispatch_sync(dispatch_get_main_queue(), ^{ [self mlw_didChangeValueForKey:key]; }); } @end