AVPlayer a été libérée, tandis que la valeur de la clé, les observateurs étaient encore inscrits
Je suis entrain de créer un simple media player app. Mon Application est écrasé lors de la première liaison est joué et j'ai cliqué sur le deuxième lien dans 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");
}
}
}
J'ai eu ce message lors de l'Application s'est écrasé.
*** Fin de l'app en raison de uncaught exception 'NSInternalInconsistencyException', la raison: Une instance de 0x165297c0
classe AVPlayer a été libérée, tandis que la valeur de la clé, les observateurs étaient encore
enregistré avec elle. Observation courante info:
( Contexte: 0x0, la Propriété: 0x1661d5d0> )'
Application s'est écrasé seulement dans IOS 8 à IOS 7 fonctionne très bien.
Ce que je fais de mal??
Vous devez vous connecter pour publier un commentaire.
J'ai eu un problème similaire. Il a bien fonctionné dans iOS 7, et maintenant il se bloque dans iOS 8.
La solution a été de supprimer l'observateur, avant de lâcher l'objet.
Lorsque vous remplacez ou d'allouer un nouvel objet pour un membre, vous êtes en libérant l'ancien objet, de sorte que vous besoin de retirer de l'observateur d'abord :
Et de même dans btnPlayClick ( dans le cas où il est pressé sans btnStop_Click d'être pressé) :
@try { [player removeObserver:self forKeyPath:@"status"]; } @catch (NSException *exception) { } @finally { }
Lors de l'utilisation de KVO vous devez équilibrer les appels à
addObserver:forKeyPath:options:context:
avec des appels àremoveObserver:forKeyPath:
(voir la KVO guide de programmation).Essayez de retirer la-vue-contrôleur comme un observateur lorsque le bouton d'arrêt est taraudé par exemple
Je n'ai rencontrer le même problème lors de l'utilisation de AVPlayer, le crash log info dit:
Que ce qu'Apple a recommandé, ce que j'ai à l'origine n'est l'ajout d'observateur après initialiser mon AVPlayerItem objet, et de supprimer le statut d'observateur dans l'observateur de la méthode dealloc. Parce que mon observateur classe gardé une référence forte sur mon AVPlayerItem objet, de sorte qu'il ne devrait pas être libéré avant mon observateur de l'objet a été libéré. Je ne sais vraiment pas pourquoi cela se produit.
J'ai donc essayé de résoudre ce problème en utilisant
BlocksKit
, il fonctionne très bien pour moi en ce moment.Il est sage de vérifier d'abord si la clé est d'être observé ou pas avant de retirer l'observateur avec un
@try @catch
, comme suit: