AVPlayer被重新分配,而关键价值观察员仍然在注册
我创build一个简单的媒体播放器应用程序。 我的应用程序崩溃时,第一个链接播放,我点击第二个链接在uitableview。
- (void)viewDidLoad { [super viewDidLoad]; arrURL = [NSArray arrayWithObjects: @"http://yp.shoutcast.com/sbin/tunein-station.pls?id=148820", @"http://www.kcrw.com/pls/kcrwmusic.pls",@"http://yp.shoutcast.com/sbin/tunein-station.pls?id=175821",@"http://yp.shoutcast.com/sbin/tunein-station.pls?id=148820",@"http://yp.shoutcast.com/sbin/tunein-station.pls?id=70931",nil]; url = [[NSURL alloc] init]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [arrURL count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *MyIdentifier = @"MyIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ; } cell.textLabel.text = [arrURL objectAtIndex:indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { selectedSongIndex = indexPath.row; url = [[NSURL alloc] initWithString:[arrURL objectAtIndex:indexPath.row]]; [self setupAVPlayerForURL:url]; [player play]; //[tableView deselectRowAtIndexPath:indexPath animated:YES]; } - (IBAction)btnPlay_Click:(id)sender { [player play]; AVPlayerItem *item = player.currentItem; [item addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionInitial| NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld| NSKeyValueObservingOptionPrior context:nil]; } - (IBAction)btnPause_Click:(id)sender { [player pause]; } - (IBAction)btnStop_Click:(id)sender { [player pause]; } -(void) setupAVPlayerForURL: (NSURL*) url1 { AVAsset *asset = [AVURLAsset URLAssetWithURL:url1 options:nil]; AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset]; player = [AVPlayer playerWithPlayerItem:anItem]; **//Application Crashed** [player addObserver:self forKeyPath:@"status" options:0 context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if([keyPath isEqualToString:@"timedMetadata"]) { AVPlayerItem *item = (AVPlayerItem *)object; NSLog(@"Item.timedMetadata: %@",item.timedMetadata); NSLog(@"-- META DATA ---"); // AVPlayerItem *pItem = (AVPlayerItem *)object; for (AVMetadataItem *metaItem in item.timedMetadata) { NSLog(@"meta data = %@",[metaItem commonKey]); NSString *key = [metaItem commonKey]; //key = publisher , key = title NSString *value = [metaItem stringValue]; NSLog(@"key = %@, value = %@", key, value); if([[metaItem commonKey] isEqualToString:@"title"]) { self.lblTitle.text = [metaItem stringValue]; } } } if (object == player && [keyPath isEqualToString:@"status"]) { if (player.status == AVPlayerStatusFailed) { NSLog(@"AVPlayer Failed"); } else if (player.status == AVPlayerStatusReadyToPlay) { NSLog(@"AVPlayer Ready to Play"); } else if (player.status == AVPlayerItemStatusUnknown) { NSLog(@"AVPlayer Unknown"); } } }
应用程序崩溃时,我收到了这条消息。
***终止应用程序由于未捕获的exception“NSInternalInconsistencyException”,原因:“AVPlayer类的实例0x165297c0被释放,而键值观察员仍然注册了它。 当前观察信息:(上下文:0x0,属性:0x1661d5d0>)
应用程序崩溃只在IOS 8 IOS 7工作正常。 我做错了什么?
我有一个类似的问题。 它在iOS 7中运行良好,现在它在iOS 8中崩溃。
解决方法是在释放对象之前移除观察者。
当你为一个成员replace或者分配一个新的对象的时候,你正在释放这个旧对象,所以你需要首先删除这个观察者:
-(void) setupAVPlayerForURL: (NSURL*) url1 { AVAsset *asset = [AVURLAsset URLAssetWithURL:url1 options:nil]; AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset]; if (player != nil) [player removeObserver:self forKeyPath:@"status"]; player = [AVPlayer playerWithPlayerItem:anItem]; [player addObserver:self forKeyPath:@"status" options:0 context:nil]; }
和btnPlayClick类似(在没有按下btnStop_Click的情况下按下):
- (IBAction)btnPlay_Click:(id)sender { if (player != nil && [player currentItem] != nil) [[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"]; AVPlayerItem *item = player.currentItem; [item addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionInitial| NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld| NSKeyValueObservingOptionPrior context:nil]; [player play]; }
使用KVO时,必须在调用addObserver:forKeyPath:options:context:
时调用removeObserver:forKeyPath:
请参阅KVO编程指南 )。
尝试删除视图控制器作为观察员停止button时,例如
- (IBAction)btnStop_Click:(id)sender { [[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"]; }
-(void)viewWillDisappear:(BOOL)animated { [self.player removeObserver:self forKeyPath:@"status" context:nil]; }
- 我的AVPlayer不应该从最后一点恢复直播
- AVPlayer问题,而直播stream媒体(iOS)
- 播放前AVPlayer停止UIActivityIndicator
- 尝试使用Swift AVPlayer播放audio
- 定时元数据与AVPlayer
- 如何在AVFoundation中循环播放video,而不会有不必要的暂停?
- 使用MPMovieController或AVFoundation可以使用NSURLProtocol的子类播放video?
- 避免video开始和结束时的模糊(甚至在使用setPreferredVideoStabilizationMode:AVCaptureVideoStabilizationModeAuto之后)?
- audio播放在Swift中作为UISlider进展