问题
I am creating a simple media player app. My App is crashed when first link is played and I clicked second link in 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");
}
}
}
I got this message when App crashed.
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x165297c0 of class AVPlayer was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x0, Property: 0x1661d5d0> )'
Application crashed only in IOS 8 in IOS 7 works fine. What I am doing wrong??
回答1:
I had a similar problem. It worked fine in iOS 7, and now it crashes in iOS 8.
The solution was to remove the observer, before releasing the object.
When you replace or allocate a new object for a member, you're releasing the old object, so you need to remove the observer first :
-(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];
}
And similarly in btnPlayClick ( in case it is pressed without btnStop_Click being pressed) :
- (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];
}
回答2:
-(void)viewWillDisappear:(BOOL)animated
{
[self.player removeObserver:self forKeyPath:@"status" context:nil];
}
回答3:
When using KVO you must balance calls to addObserver:forKeyPath:options:context: with calls to removeObserver:forKeyPath: (see the KVO programming guide).
Try removing the view controller as an observer when the stop button is tapped e.g.
- (IBAction)btnStop_Click:(id)sender {
[[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"];
}
回答4:
I did meet the similar issue when using AVPlayer, the crash log info says:
An instance 0x174034600 of class AVKeyPathFlattener was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x0, Property: 0x17405d6d0> )
As what Apple recommended, what I originally did is adding observer after initialize my AVPlayerItem object, and remove observer in the observer's dealloc method. Because my observer class kept a strong reference on my AVPlayerItem object, so it should not be deallocated before my observer object was deallocated. I really don't know why this happens.
So I tried solved this problem by using BlocksKit, it works fine for me right now.
回答5:
It's wise to verify first if the key is being observed or not before removing the observer with a @try @catch, like so:
@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");
}
来源:https://stackoverflow.com/questions/26256982/avplayer-was-deallocated-while-key-value-observers-were-still-registered-with-it