2017-03-07 3 views
0

Ich bekomme den folgenden Fehler, aber die seltsame Sache ist, dass es nur passiert, wenn ich einen Scroll auf meinem Tableview mit der Seitenumbruch, Laden einer zweiten Reihe von Posts, und als ich versuche, neue view-Controller, um aus, , wenn ich nur die erste Seite der Beiträge zu laden, und zu einer anderen Ansicht Controller bewegen, gibt es keinen Absturz:Klasse AVPlayerItem wurde freigegeben, während Schlüsselwertbeobachter noch registriert wurden

Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'An instance 0x170212330 of class AVPlayerItem was deallocated while key 
value observers were still registered with it. 
Current observation info: <NSKeyValueObservationInfo 0x174820360> (
<NSKeyValueObservance 0x174244290: Observer: 0x101c76c00, Key path: 
playbackBufferEmpty, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, 
Property: 0x174243ea0> 
<NSKeyValueObservance 0x1754583c0: Observer: 0x101c76c00, Key path: 
playbackLikelyToKeepUp, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, 
Property: 0x174243f60> 

ich habe einen Spieler auf meiner Zelle , hier ist mein Code für die Ansicht Controller:

- (UITableViewCell *)tableView:(UITableView *)tableViewSelected cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSString *identifier = @"postCell"; 
    PostCell* updateCell = [tableViewSelected dequeueReusableCellWithIdentifier:identifier]; 

     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 

     dispatch_async(queue, ^{ 

      dispatch_sync(dispatch_get_main_queue(), ^{ 
       NSLog(@"ADD VIDEO PLAYER and PLAY VIDEO"); 



       NSString* videoString = [NSString stringWithFormat:@"%@%@%@",UrlBase,PostVideos,post.video]; 
       NSString* expandedPath = [videoString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
       NSURL *videoURL = [NSURL URLWithString:expandedPath]; 
       NSLog(@"URL : %@",videoURL); 


       updateCell.videoItem = [AVPlayerItem playerItemWithURL:videoURL]; 

       [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 
       [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 

       updateCell.videoPlayer = [AVPlayer playerWithPlayerItem:updateCell.videoItem]; 
       updateCell.avLayer = [AVPlayerLayer playerLayerWithPlayer:updateCell.videoPlayer]; 
       updateCell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 

       [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil]; 
       [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:[updateCell.videoPlayer currentItem]]; 


       updateCell.avLayer.frame = updateCell.picture.bounds; 
       [updateCell.videoView.layer addSublayer:updateCell.avLayer]; 

       [updateCell.avLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 
       if(indexPath.row==0){ 
        [updateCell.videoPlayer play]; 
       } 
      }); 
     }); 
     return updateCell; 

} 

Und der einzige Unterschied, den ich aus Hinzufügen einer zweiten Seite sehen kann, ist:

Wenn regulären Tabellenansicht Last tun ich tun:

[_tableView reloadData]; 

Wenn eine zweite Seite auf der gleichen Tabellenansicht lade ich tun:

[_tableView beginUpdates]; 
[_tableView insertRowsAtIndexPaths:[[GlobalSingleton sharedInstance] indexPathsToInsert] withRowAnimation:UITableViewRowAnimationTop]; 
[_tableView endUpdates]; 

als auf meinem Handy ich tun:

- (void)prepareForReuse{ 
    [self removePlayer]; 

} 

- (void) dealloc { 
[self removePlayer]; 
} 

-(void)removePlayer{ 
    @try{ 

    [self.videoItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; 
    [self.videoItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; 




    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 

     NSLog(@"remove Observer!"); 
    // [avLayer.player pause]; 
    } 
    @catch (NSException * e) { 
     NSLog(@"Exception: %@", e); 
    } 
    @finally { 
     NSLog(@"finally"); 
     [self.avLayer removeFromSuperlayer]; 
     self.playIV.hidden = YES; 
     self.videoActivity.hidden = YES; 
     self.videoView.hidden = YES; 
     self.videoItem = nil; 
     self.avLayer = nil; 
     self.videoPlayer = nil; 
    } 

} 

Ist es möglich, dass insertRowsAtI ndexPaths bewirkt, dass die Zellen niemals dealloc werden? Ich kann nicht herausfinden, wie es möglich ist, die Beobachter registrieren zu lassen.

+0

Meine Lösung, die 2 zu entfernen war erste Beobachter: [updateCell.videoItem addObserver: updateCell forKeyPath: @ "playbackBufferEmpty" Optionen: NSKeyValueObservingOptionNeuer Kontext: nil]; [updateCell.videoItem addObserver: updateCell forKeyPath: @ "playbackLikelyToKeepUp" Optionen: NSKeyValueObservingOptionNeuer Kontext: nil]; –

+0

Auch ich habe herausgefunden prepareForReuse funktioniert nicht gut mit insertRowsAtIndexPaths, aber wenn ich die Beobachter auf cellForRowAtIndexPath vor dem Erstellen des neuen videoItem entfernen, funktioniert es auch. –

Antwort

0

Irgendwie, wenn die insertRowsAtIndexPaths verwenden, wird die prepareForReuse nicht genannt worden, so beschloß ich, es durch Aufheben der Registrierung der Beobachter auf der cellForRowAtIndexPath, bevor eine neue VideoItem zu der Zelle hinzugefügt:

- (UITableViewCell *)tableView:(UITableView *)tableViewSelected cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
NSString *identifier = @"postCell"; 
PostCell* updateCell = [tableViewSelected dequeueReusableCellWithIdentifier:identifier]; 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 

    dispatch_async(queue, ^{ 

     dispatch_sync(dispatch_get_main_queue(), ^{ 
      NSString* videoString = [NSString stringWithFormat:@"%@%@%@",UrlBase,PostVideos,post.video]; 
      NSString* expandedPath = [videoString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
      NSURL *videoURL = [NSURL URLWithString:expandedPath]; 

      /** SOLUTION STARTS HERE **/ 
      @try{ 
        [self.videoItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; 
        [self.videoItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; 
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:nil]; 
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 

      } 
      @catch (NSException * e) { 
       NSLog(@"Exception: %@", e); 
      } 
      @finally { 
       NSLog(@"finally"); 
      } 
      /** SOLUTION ENDS HERE **/ 

      updateCell.videoItem = [AVPlayerItem playerItemWithURL:videoURL]; 
      [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 
      [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 

      updateCell.videoPlayer = [AVPlayer playerWithPlayerItem:updateCell.videoItem]; 
      updateCell.avLayer = [AVPlayerLayer playerLayerWithPlayer:updateCell.videoPlayer]; 
      updateCell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 

      [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil]; 
      [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:[updateCell.videoPlayer currentItem]]; 


      updateCell.avLayer.frame = updateCell.picture.bounds; 
      [updateCell.videoView.layer addSublayer:updateCell.avLayer]; 

      [updateCell.avLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 
      if(indexPath.row==0){ 
       [updateCell.videoPlayer play]; 
      } 
     }); 
    }); 
    return updateCell; 

} 
Verwandte Themen