2014-07-18 18 views
7

Mam tablicę zawierającą URLS wideo, chcę odtwarzać te filmy na UITableviewcell, gdy jest w pełni widoczny.Odtwórz wideo na UITableViewCell, gdy jest całkowicie widoczny

Próbowałem to

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView 
{ 
    NSArray* cells = homeTabl.visibleCells; 

    for (HomeCell* cell in cells) 
    { 
     if (cell.frame.origin.y > offset.y && 
     cell.frame.origin.y + cell.frame.size.height < offset.y + bounds.size.height) 
     { 
      NSIndexPath *path = [homeTabl indexPathForCell:cell] ; 
      index = path.row; 
      fullvisible = YES; 
      [homeTabl reloadData]; 
     } 
     else 
     { 
      fullvisible = NO; 
     } 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (fullvisible) 
    { 
      NSURL *url = [NSURL URLWithString:[[responsearray objectAtIndex:indexPath.row]valueForKey:@"feed_video"]]; 

      cell.videoItem = [AVPlayerItem playerItemWithURL:url]; 
      cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem]; 
      cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer]; 
      cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 
      [cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 
      [cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil]; 
      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 

      cell.avLayer.frame = CGRectMake(5, 9, 310, 310); 
      [cell.contentView.layer addSublayer:cell.avLayer]; 
      [cell.videoPlayer play]; 
      [cell.contentView addSubview:cell.videoActivity]; 
    } 
    else 
    { 
     cell.videoPlayer = nil; 
     [cell.avLayer removeFromSuperlayer]; 
     cell.videoItem = nil; 
     [cell.videoPlayer pause]; 
    } 
} 

Działa to dobrze - ale to straszne spowolni przewijanie widoku tabeli. Proszę zasugerować mi inną lepszą metodę.

+5

co jest videoActivity? –

+0

@MitulNakum Jest to wskaźnik aktywności. –

Odpowiedz

9

Można użyć

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 
    isScrolling = NO; 
    [homeTabl reloadData]; 
} 

-(void)scrollViewWillBeginDragging:(UIScrollView *)aScrollView 
{ 
    isScrolling = YES; 
    [homeTabl reloadData]; 
    index = -1; 
} 

aw cellForRowAtIndexPath

if (fullvisible && index == indexPath.row) { 
     if (!isScrolling) { 

      NSLog(@"video index---%d",indexPath.row); 

      if (index == indexPath.row) { 
       NSLog(@"video index---%d",indexPath.row); 
       cell.videoActivity.hidden = NO; 

       // if (index == indexPath.row) { 
       NSURL *url = [NSURL URLWithString:[[responsearray objectAtIndex:indexPath.row]valueForKey:@"feed_video"]]; 

       dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 

       dispatch_async(queue, ^{ 
        cell.videoItem = [AVPlayerItem playerItemWithURL:url]; 

        dispatch_sync(dispatch_get_main_queue(), ^{ 
         cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem]; 
         cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer]; 
         cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 
         [cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 
         [cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 

         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil]; 
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 

         cell.avLayer.frame = CGRectMake(5, 9, 310, 310); 
         [cell.contentView.layer addSublayer: cell.avLayer]; 
         [ cell.videoPlayer play]; 
         [cell.contentView addSubview:cell.videoActivity]; 
        }); 
       }); 
       //    } 
       //    else{ 
       //     cell.videoActivity.hidden = YES; 
       //     cell.videoPlayer = nil; 
       //     [cell.avLayer removeFromSuperlayer]; 
       //     cell.videoItem = nil; 
       //     [cell.videoPlayer pause]; 
       //    } 
      } 
     }} 

    else{ 

     cell.videoActivity.hidden = YES; 
     cell.videoPlayer = nil; 
     [cell.avLayer removeFromSuperlayer]; 
     cell.videoItem = nil; 
     [cell.videoPlayer pause]; 

    } 
+0

możesz odpowiedzieć na http://stackoverflow.com/questions/34767717/tableview-cell-video-autoplay? –

+0

@nNthin M Keloth - Co to jest ten pełnoprawny bool? –

+0

@Nitin Co to za widza i indeks? Gdzie możemy zwiększyć indeks? –

8

Ładowanie elementów wideo jest równoznaczne z głównym wątkiem; oznacza to, że elementy wideo są pobierane i ładowane w komórkach widoku tabeli w tym samym czasie, gdy tworzone są komórki widoku tabeli. To powoduje problem i powoduje, że przewijanie jest bardzo opóźnione i powolne. Aby rozwiązać problem, musisz załadować swoje filmy asynchronicznie, w osobnym wątku.

Dlatego należy unikać ładowania obrazów synchronicznie, ale asynchronicznie, używając innego wątku niż główny wątek, aby przewijanie i ładowanie + wyświetlanie obrazów były wykonywane w sposób zależny, unikając jakiegokolwiek opóźnienia.

Jest to prawdopodobnie zduplikowane pytanie, ponieważ zostało już zadane i istnieją tutoriale, ale ponieważ zawsze miałem problem z tym (ale na zdjęciach) w mojej pierwszej aplikacji na iOS i uznałem, że jest to bardzo mylące, tutaj zamieszczam odpowiedź, mając nadzieję, że jest to pomocne.

Spróbuj przenieść wszystkie linie powiązane z obciążeniem/wyświetlaniem wideo, w szczególności playerItemWithURL w swoim - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath: do osobnego bloku. Również szukaj i przeczytaj inny post na temat "asynchronicznego ładowania wideo w komórkach widoku tabeli". Istnieje wiele dogłębnych samouczków i pytań i odpowiedzi na ten temat.

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 

dispatch_async(queue, ^{ 
cell.videoItem = [AVPlayerItem playerItemWithURL:url]; 

dispatch_sync(dispatch_get_main_queue(), ^{ 
    cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem]; 
     cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer]; 
     cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 
     [cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 
     [cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil]; 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 

     cell.avLayer.frame = CGRectMake(5, 9, 310, 310); 
     [cell.contentView.layer addSublayer: cell.avLayer]; 
     [ cell.videoPlayer play]; 
     [cell.contentView addSubview:cell.videoActivity]; 
    }); 
}); 
+0

Czy mógłbyś podzielić się z nami tym, jak radzisz sobie z usuwaniem kontrolera widoku jako obserwatora dla komórki.VideoItem dla playbackBufferEmpty i playbackLikelyToKeepUp? – user3344977

+0

To było bardzo pomocne! Dziękujemy za opublikowanie tego kodu :) – Elad

+0

Wow ... to działa jak urok !!!! Dzięki! Dobra robota – Anita

0

Unikaj ponownego ładowania widoku tabeli za każdym razem, gdy chcesz odtworzyć wideo. Możesz wykonać kod odtwarzania wideo w widocznej komórce bez konieczności ponownego ładowania całego widoku tabeli.

Podejrzewam również, że nie chcesz odtwarzać wideo, dopóki widok tabeli nie przestanie się przewijać. Zobacz: How to detect when a UIScrollView has finished scrolling (wykrywanie, kiedy zakończono przewijanie UIScrollView jest zaskakująco mało intuicyjne).

Jeśli naprawdę chcesz rozpocząć odtwarzanie wideo, zanim przewijanie przestanie się przewijać, przynajmniej zmodyfikuj kod, aby sprawdzić, czy widoczna komórka już gra, a następnie nie rób nic. W tej chwili Twój kod tableView:cellForRowAtIndexPath:, który odtwarza wideo, jest wykonywany wiele, wiele razy, gdy komórka jest w pełni widoczna (co, jak podejrzewam, dzieje się bardzo często!).

Powiązane problemy