简体   繁体   中英

Send NSNotification in observeValueForKeyPath

I have a AVPlayer with a rate observer.

[self.player addObserver:self
                          forKeyPath:@"rate"
                             options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
                             context:&RateContext];

In my observeValueForKeyPath method, I am trying to send a notification to let the playerLayer superView know when the player has started/stopped.

- (void)observeValueForKeyPath:(NSString *)keyPath
                  ofObject:(id)object
                    change:(NSDictionary<NSString *,id> *)change
                   context:(void *)context {

    if ([keyPath isEqualToString:@"rate"]) {
        if (self.player.rate == 0) {
            [self.indicatorView startAnimating];
            dispatch_async(dispatch_get_main_queue(), ^{
                 [[NSNotificationCenter defaultCenter] postNotificationName:@"playerStopped" object:nil];
             });
            [self videoStalled];
        }else if (self.player.rate == 1){
            [self.indicatorView stopAnimating];
          //dispatch_async(dispatch_get_main_queue(), ^{
          //   [[NSNotificationCenter defaultCenter] postNotificationName:@"playerStarted" object:nil userInfo:dic];
          //});
        }
        return;
    }

In my videoStalled I wait until more of the video has loaded then call [self.player play] . "Rate" is then called and the video will play instantly ONLY IF I comment out the notification post. When I uncomment the notification, "Rate" is still called but the player doesn't play until a few seconds later. Not sure where the big lag is coming from.

Use a few NSLog calls to show where the flow goes and what time is spent where.

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSString *,id> *)change
                       context:(void *)context {

    if ([keyPath isEqualToString:@"rate"]) {
        if (self.player.rate == 0) {
            [self.indicatorView startAnimating];
            [self videoStalled];
            NSLog(@"stage 1");
            [[NSNotificationCenter defaultCenter] postNotificationName:@"playerStopped" object:nil];
        }else if (self.player.rate == 1){
            [self.indicatorView stopAnimating];
            //dispatch_async(dispatch_get_main_queue(), ^{
            //   [[NSNotificationCenter defaultCenter] postNotificationName:@"playerStarted" object:nil userInfo:dic];
            //});
        }
        return;
    }
}

- (void) playerStopped
{
    NSLog(@"stage 2");
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"stage 3");
        [self.player play];
    });
}

That way you'll see whether it is a thread that is slowing things down. You might also just use another observer instead of a notification to trigger a call to your playStopped method. I've found that notifications are best used in less time critical situations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM