ios objective-c avplayer avplayeritem

ios - AVPlayer fue desasignado mientras los observadores de valor clave todavía estaban registrados con él



objective-c avplayeritem (4)

Al usar KVO, debe equilibrar las llamadas a addObserver:forKeyPath:options:context: con llamadas a removeObserver:forKeyPath: (consulte la guía de programación de KVO ).

Intente eliminar el controlador de vista como observador cuando se toca el botón de detener, por ejemplo

- (IBAction)btnStop_Click:(id)sender { [[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"]; }

Estoy creando una aplicación de reproductor de medios simple. Mi aplicación se bloquea cuando se reproduce el primer enlace y hice clic en el segundo enlace en 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"); } } }

Recibí este mensaje cuando la aplicación se estrelló.

*** Aplicación de terminación debido a la excepción no detectada ''NSInternalInconsistencyException'', razón: ''Se desclasificó una instancia 0x165297c0 de la clase AVPlayer mientras que los observadores de valores clave todavía estaban registrados con ella. Información de observación actual: (Contexto: 0x0, Propiedad: 0x1661d5d0>) ''

La aplicación solo se bloqueó en IOS 8 en IOS 7 funciona bien. ¿¿Que estoy haciendo mal??


Encontré el problema similar cuando uso AVPlayer, la información del registro de fallos dice:

Se desasignó una instancia 0x174034600 de la clase AVKeyPathFlattener mientras los observadores de valores clave todavía estaban registrados con ella. Información de observación actual: (Contexto: 0x0, Propiedad: 0x17405d6d0>)

Como lo que Apple recomendó, lo que originalmente hice fue agregar observador después de inicializar mi objeto AVPlayerItem y eliminar observador en el método dealloc del observador. Debido a que mi clase de observador mantuvo una fuerte referencia en mi objeto AVPlayerItem, no debería ser desasignado antes de que mi objeto observador fuera desasignado. Realmente no sé por qué sucede esto.

Así que intenté resolver este problema usando BlocksKit , funciona bien para mí ahora mismo.


Tuve un problema similar. Funcionó bien en iOS 7, y ahora se bloquea en iOS 8.

La solución fue eliminar el observador, antes de liberar el objeto.

Cuando reemplaza o asigna un nuevo objeto para un miembro, está liberando el objeto anterior, por lo que primero debe eliminar el observador:

-(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]; }

Y de manera similar en btnPlayClick (en caso de que se presione sin presionar 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]; }


-(void)viewWillDisappear:(BOOL)animated { [self.player removeObserver:self forKeyPath:@"status" context:nil]; }