Ios AVPlayer被解除分配,而key value Observators仍在注册
我正在创建一个简单的媒体播放器应用程序。播放第一个链接时,我的应用程序崩溃,我在uitableview中单击了第二个链接Ios AVPlayer被解除分配,而key value Observators仍在注册,ios,objective-c,avplayer,avplayeritem,Ios,Objective C,Avplayer,Avplayeritem,我正在创建一个简单的媒体播放器应用程序。播放第一个链接时,我的应用程序崩溃,我在uitableview中单击了第二个链接 - (void)viewDidLoad { [super viewDidLoad]; arrURL = [NSArray arrayWithObjects: @"http://yp.shoutcast.com/sbin/tunein-station.pls?id=148820", @"http://www.kcrw.com/pls/kcrwmu
- (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");
}
}
}
应用程序崩溃时我收到了这条消息
***由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因是:“的实例0x165297c0”
当键值观察者仍在时,类AVPlayer被解除分配
向它登记。当前观测信息:
(上下文:0x0,属性:0x1661d5d0>)'
应用程序仅在IOS 7中的IOS 8中崩溃,工作正常。
我做错了什么???在使用KVO时,您必须平衡对
addObserver:forKeyPath:options:context:
的调用和对removeObserver:forKeyPath:
的调用(请参阅)
当点击停止按钮时,尝试将视图控制器作为观察者移除,例如:
- (IBAction)btnStop_Click:(id)sender {
[[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"];
}
我也有类似的问题。它在iOS 7中运行良好,现在在iOS 8中崩溃 解决方案是在释放对象之前移除观察者 为成员替换或分配新对象时,将释放旧对象,因此需要首先删除观察者:
-(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的情况下按下):
我在使用AVPlayer时遇到过类似的问题,崩溃日志信息显示: AvKeyPathFlatter类的实例0x174034600已解除分配,而键值观察员仍在该实例中注册。当前观察信息:(上下文:0x0,属性:0x17405d6d0>) 正如苹果所建议的,我最初做的是在初始化我的AVPlayerItem对象后添加observer,并在observer的dealloc方法中删除observer。因为我的observer类在我的AVPlayerItem对象上保留了一个强引用,所以在我的observer对象被释放之前不应该释放它。我真的不知道为什么会这样
因此,我尝试使用解决了这个问题,它现在对我来说很好。明智的做法是,在使用
@try@catch
移除观察者之前,先验证是否观察到了密钥,如下所示:
@try {
[self.player removeObserver:self forKeyPath:@"status" context:nil];
} @catch (id anException) {
//do nothing, obviously it wasn't attached because an exception was thrown
NSLog(@"status key not being observed");
}
应用程序崩溃。崩溃日志:'无法从中删除密钥路径“timedMetadata”的观察者,因为它未注册为观察者。'应用程序仅在IOS 8设备中崩溃。mmcombe是正确的,但错误涉及AVPlayer的状态“KVO”。只需将他的答案改为[[player]removeObserver:self forKeyPath:@“status”];我的应用程序在IOS 8中崩溃,下面是我的崩溃日志:“由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因是:'在键值观察器仍在注册的情况下,AVPlayerItem类的一个实例0x15edf250被释放。”我将此设置为if(player!=nil){if(player.currentItem!=nil){[player.currentItem removeObserver:self-forKeyPath:@“status”];}}而不是if(player!=nil)[player-removeObserver:self-forKeyPath:@“status”];对我来说效果很好。大家好,我也遇到了这个问题,在过去的两天里一直在寻找解决方案。请帮助我解决这个问题。我在这里发布了一个问题-我实现了您的代码,但由于未捕获的异常“NSRangeException”,导致终止应用程序时出错,原因是:“无法删除关键路径“状态”的观察者”来自,因为它没有注册为观察者。这将导致“无法从中删除关键路径的观察者”状态的异常,因为它没有注册为观察者。@AbuzarAmin为此使用try-catch。
@try{[player-removeObserver:self-forKeyPath:@“status”;}@catch(NSException*exception){}@finally{}
您能否提供一点解决方案的背景信息?虽然欢迎使用此代码片段,并且可能会提供一些帮助,但它将说明如何以及为什么解决此问题。请记住,您是在为将来的读者回答问题,而不仅仅是现在的提问者!请您的回答添加解释,并给出相关说明适用的限制和假设。
-(void)viewWillDisappear:(BOOL)animated
{
[self.player removeObserver:self forKeyPath:@"status" context:nil];
}
@try {
[self.player removeObserver:self forKeyPath:@"status" context:nil];
} @catch (id anException) {
//do nothing, obviously it wasn't attached because an exception was thrown
NSLog(@"status key not being observed");
}