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

[expo-av] Prevent debugger from breaking when removing observations #9334

Merged
merged 5 commits into from
Jul 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 packages/expo-av/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

- Fix audio recording after reload. ([#9283](https://github.com/expo/expo/pull/9283) by [@IjzerenHein](https://github.com/IjzerenHein))
- Fix fullscreen events not emitted on iOS. ([#9323](https://github.com/expo/expo/pull/9323) by [@IjzerenHein](https://github.com/IjzerenHein))
- Prevent debugger break when removing observations. ([#9334](https://github.com/expo/expo/pull/9334) by [@IjzerenHein](https://github.com/IjzerenHein))

## 8.3.0 — 2020-07-08

Expand Down
52 changes: 36 additions & 16 deletions packages/expo-av/ios/EXAV/EXAVPlayerData.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ @interface EXAVPlayerData ()
@property (nonatomic, strong) id <NSObject> timeObserver;
@property (nonatomic, strong) id <NSObject> finishObserver;
@property (nonatomic, strong) id <NSObject> playbackStalledObserver;
@property (nonatomic, strong) NSMapTable<NSObject *, NSMutableSet<NSString *> *> *observers;

@property (nonatomic, strong) NSNumber *progressUpdateIntervalMillis;
@property (nonatomic, assign) CMTime currentPosition;
Expand Down Expand Up @@ -88,6 +89,7 @@ - (instancetype)initWithEXAV:(EXAV *)exAV
_finishObserver = nil;
_playbackStalledObserver = nil;
_statusUpdateCallback = nil;
_observers = [NSMapTable new];

// These status props will be potentially reset by the following call to [self setStatus:parameters ...].
_progressUpdateIntervalMillis = @(500);
Expand Down Expand Up @@ -129,8 +131,8 @@ - (void)_loadNewPlayer
strongSelf.items = @[firstplayerItem, secondPlayerItem, thirdPlayerItem];
strongSelf.player = [AVQueuePlayer queuePlayerWithItems:@[firstplayerItem, secondPlayerItem, thirdPlayerItem]];
if (strongSelf.player) {
[strongSelf.player addObserver:strongSelf forKeyPath:EXAVPlayerDataObserverStatusKeyPath options:0 context:nil];
[strongSelf.player.currentItem addObserver:strongSelf forKeyPath:EXAVPlayerDataObserverStatusKeyPath options:0 context:nil];
[strongSelf _addObserver:strongSelf.player forKeyPath:EXAVPlayerDataObserverStatusKeyPath];
[strongSelf _addObserver:strongSelf.player.currentItem forKeyPath:EXAVPlayerDataObserverStatusKeyPath];
} else {
NSString *errorMessage = @"Load encountered an error: [AVPlayer playerWithPlayerItem:] returned nil.";
if (strongSelf.loadFinishBlock) {
Expand Down Expand Up @@ -509,12 +511,35 @@ - (void)replayWithStatus:(NSDictionary *)status

#pragma mark - Observers

- (void)_addObserver:(NSObject *)object forKeyPath:(NSString *)path
{
[self _addObserver:object forKeyPath:path options:0];
}

- (void)_addObserver:(NSObject *)object forKeyPath:(NSString *)path options:(NSKeyValueObservingOptions)options
{
NSMutableSet<NSString *> *set = [_observers objectForKey:object];
if (set == nil) {
set = [NSMutableSet set];
[_observers setObject:set forKey:object];
}
if (![set containsObject:path]) {
[set addObject:path];
[object addObserver:self forKeyPath:path options:0 context:nil];
}
}

- (void)_tryRemoveObserver:(NSObject *)object forKeyPath:(NSString *)path
{
@try {
[object removeObserver:self forKeyPath:path];
} @catch (NSException *exception) {
// no-op
NSMutableSet<NSString *> *set = [_observers objectForKey:object];
if (set) {
if ([set containsObject:path]) {
[set removeObject:path];
if (!set.count) {
[_observers removeObjectForKey:object];
}
[object removeObserver:self forKeyPath:path];
}
}
}

Expand Down Expand Up @@ -602,11 +627,8 @@ - (void)_addObserversForPlayerItem:(AVPlayerItem *)playerItem
object:[_player currentItem]
queue:nil
usingBlock:playbackStalledObserverBlock];
[self _tryRemoveObserver:playerItem forKeyPath:EXAVPlayerDataObserverPlaybackBufferEmptyKeyPath];
[playerItem addObserver:self forKeyPath:EXAVPlayerDataObserverPlaybackBufferEmptyKeyPath options:0 context:nil];

[self _tryRemoveObserver:playerItem forKeyPath:EXAVPlayerDataObserverStatusKeyPath];
[playerItem addObserver:self forKeyPath:EXAVPlayerDataObserverStatusKeyPath options:0 context:nil];
[self _addObserver:playerItem forKeyPath:EXAVPlayerDataObserverPlaybackBufferEmptyKeyPath];
[self _addObserver:playerItem forKeyPath:EXAVPlayerDataObserverStatusKeyPath];
}

- (void)_updateTimeObserver
Expand Down Expand Up @@ -643,15 +665,13 @@ - (void)_addObserversForNewPlayer
[self _removeObservers];
[self _updateTimeObserver];

[_player addObserver:self forKeyPath:EXAVPlayerDataObserverRateKeyPath options:0 context:nil];
[self _addObserver:_player forKeyPath:EXAVPlayerDataObserverRateKeyPath];
NSUInteger currentItemObservationOptions = NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew;
[_player addObserver:self forKeyPath:EXAVPlayerDataObserverCurrentItemKeyPath options:currentItemObservationOptions context:nil];
[_player addObserver:self forKeyPath:EXAVPlayerDataObserverTimeControlStatusPath options:0 context:nil]; // Only available after iOS 10
[self _addObserver:_player forKeyPath:EXAVPlayerDataObserverCurrentItemKeyPath options:currentItemObservationOptions];
[self _addObserver:_player forKeyPath:EXAVPlayerDataObserverTimeControlStatusPath]; // Only available after iOS 10
[self _addObserversForPlayerItem:_player.currentItem];
}



- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
Expand Down