Ändern playerItem der AVPlayer in UITableView

Ich habe eine UITableView mit einer Anzahl von videos und spielen beim scrollen. Da die Zellen in der tableView werden wieder verwendet, ich habe nur Instanzierung einer AVPlayer für jede Zeile, immer. Wenn eine Zelle wieder verwendet, die ich ändern Sie einfach die PlayerItem von der Zelle player durch den Aufruf [self.player replaceCurrentItemWithPlayerItem:newItem];. Dies wird derzeit indirekt aufgerufen, in tableView:cellForRowAtIndexPath. Wenn Sie nach unten scrollen, es gibt eine merkliche Verzögerung, wenn die re-Nutzung Auftritt. Mit einen Prozess der Beseitigung, habe ich festgestellt, dass die lags verursacht durch replaceCurrentItemWithPlayerItem, bevor es auch nur angefangen zu spielen. Beim entfernen dieser Zeile code (verhindern, dass der Spieler immer eine neue video -) die Gummierung verschwindet.

, Was ich versucht habe um es zu beheben:

Habe ich eine benutzerdefinierte UITableViewCell für die Wiedergabe dieser videos, und ich habe eine Methode in diesen zu initialisieren, mit den neuen Informationen aus einem Objekt. I. E, in cellForRowAtIndexPath: ich nenne [cell initializeNewObject:newObject]; zum ausführen der folgenden Methode:

//In CustomCell.m
-(void)initializeNewObject:(CustomObject*)newObject
{ /*...*/
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        AVPlayerItem *xPlayerItem = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:newObject.url]];
        AVPlayer *dummy = self.player;
        [dummy replaceCurrentItemWithPlayerItem:xPlayerItem];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.player = dummy;
            playerItem = xPlayerItem;
        }
    }/*...*/
}

Beim laufen, bekomme ich das gleiche Ergebnis wie wenn ich komplett entfernt werden, der Aufruf für den Austausch der Sache. Offenbar, diese Funktion kann nicht eingefädelt werden.
Ich bin mir nicht ganz sicher, was ich erwartete von dieser. Ich könnte mir vorstellen, ich brauche eine saubere copy des AVPlayer für diese zu arbeiten, aber nach der Suche noch ein bisschen, ich fand einige Kommentare, die besagt, dass replaceCurrentItemWithPlayerItem: können nicht aufgerufen werden, in einem separaten thread, das macht für mich keinen Sinn. Ich weiß, dass UI-Elemente sollten niemals behandelt werden, die in anderen threads als Haupt - /UI-thread, aber ich hätte mir nie vorstellen replaceCurrentItemWithPlayerItem fallen unter diese Kategorie.

Ich bin jetzt auf der Suche nach einer Möglichkeit, ändern Sie das Element von einer AVPlayer ohne lag, aber finde keine. Ich hoffe, ich habe verstanden das einfädeln diese Funktion falsch ist, und dass jemand korrigieren würde.. mich

EDIT:
Ich habe mich jetzt schon informiert, dass dieser Anruf ist bereits Gewinde, und dass dies nicht wirklich passieren. Allerdings sehe ich keine andere Erklärung.. Unten ist meine cellForRowAtIndexPath:. Es ist in einem speziell UITableView mit den Delegierten festgelegt self (so self == tableView)

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomCell *cell = [self dequeueReusableCellWithIdentifier:kCellIdentifier];
    if(!cell)
        cell = [[[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil] objectAtIndex:0];

    //Array 'data' contains all objects to be shown. The objects each have titles, url's etc.
    CustomVideoObject *currentObject = [data objectAtIndex:indexPath.row];
    //When a cell later starts playing, I store a pointer to the cell in this tableView named 'playing'
    //After a quick scroll, the dequeueing cell might be the cell currently playing - resetting
    if(playing == cell)
        playing = nil;
    //This call will insert the correct URL, title, etc for the new video, in the custom cell
    [cell initializeNewObject:currentObject];
    return cell;
}

Den initializeNewObject aktuell "arbeiten", jedoch hinken (dies ist innerhalb CustomCell.m:

-(void)initializeNewObject:(CustomObject*)o
{
    //If this cell is being dequeued/re-used, its player might still be playing the old file
    [self.player pause];
    self.currentObject = o;
    /*
    //Setting text-variables for title etc. Removed from this post, but by commenting them out in the code, nothing improves.
    */

    //Replace the old playerItem in the cell's player
    NSURL *url = [NSURL URLWithString:self.currentObject.url];
    AVAsset *newAsset = [AVAsset assetWithURL:url];
    AVPlayerItem *newItem = [AVPlayerItem playerItemWithAsset:newAsset];
    [self.player replaceCurrentItemWithPlayerItem:newItem];

    //The last line above, replaceCurrentItemWithPlayerItem:, is the 'bad guy'.
    //When commenting that one out, all lag is gone (of course, no videos will be playing either)
    //The lag still occurs even if I never call [self.player play], which leads me
    //to believe that nothing after this function can cause the lag

    self.isPlaying = NO;
}

Dem lag passiert an der exakt gleichen Stelle jeder Zeit. Beim scrollen schnell nach unten, können wir sehen, dass die kurze Verzögerung geschieht, wenn der Obere Teil der unteren Zelle, erreicht die Mitte des Bildschirms. Ich denke, das bedeutet nichts zu Ihnen, aber es ist klar, dass die Verzögerung geschieht an der exakt gleichen Stelle jedes mal, und zwar dann, wenn eine neue Zelle dequeueing. Nach dem ändern der playerItem der AVPlayer ich tun nichts. Ich nicht anfangen zu spielen das video erst später. replaceCurrentItemWithPlayerItem: ist dies verursacht merkliche Verzögerung. Die Dokumentation besagt, dass es ändert sich das Element in einem anderen thread, aber etwas in dieser Methode hält sich meine UI.

Wurde mir gesagt, ich nutze Mal Profiler in Instrumenten, um herauszufinden, was es ist, aber ich habe keine Ahnung, wie das geht. Durch ausführen der profiler, und scrollen Sie einmal in eine Weile, dies ist das Ergebnis(Bild). Die peaks der einzelnen graph-Gruppe ist die lag-ich spreche. Die einzigen extremen peak ist (denke ich), wenn ich musste Bildlauf nach unten und tippte auf die Statusleiste, um einen Bildlauf nach oben. Ich weiß nicht, wie das Ergebnis zu interpretieren ist. Ich suchte den Stapel für replace, und fand den bastard. Es heißt hier innerhalb Main Thread (an der Spitze), was Sinn macht, mit einer "Laufzeit" von 50ms, das ich keine Ahnung habe, zu denken. Der relevante Teil des Graphen ist von einer Zeitspanne von ungefähr 1 minute und eine Hälfte.
Im Vergleich, wenn das auskommentieren der einzelnen Zeile und Laufzeit-Profiler wieder, die Grafik der Gipfel sind deutlich niedriger (Höchster peak bei 13%, im Vergleich zu dem, was auf dem Bild, das ist wahrscheinlich rund 60-70%).

Ich weiß nicht, was Sie suchen..

  • Ich habe das gleiche Problem. Haben Sie es fest irgendwie?
  • Nein.. :/ ich beschloss, nur starten Sie die Wiedergabe, wenn der Bildlauf gestoppt hatte, statt. So kann ich scrollen, vorbei an vielen videos (mit richtigen thumbnails), ohne das video überhaupt geladen werden, und nur lädt, wenn das scrollen Stoppt über es. Nicht wirklich, was ich wollte, aber besser als der lag. Lassen Sie mich wissen, wenn Sie etwas herausfinden!
  • wie kommen Sie und setzen Sie das video-thumbnail?
  • Nicht sicher, dass replaceCurrentItemWithPlayerItem selbst ist das Problem. Ich habe versucht unter Beibehaltung aller AVPlayers (1 pro Zelle) und einfach tauschen AVPlayerLayer die Spieler für jede Zelle. Also nie ruft replaceCurrentItemWithPlayerItem wie jedes AVPlayer ist nur eine AVPlayerItem. Die lag ist immer noch da und tritt auch beim Austausch der AVPlayerLayer die Spieler auf eine bereits bestehende AVPlayer.
  • Hast du irgendeine Lösung dafür? Ich bin auch stecken geblieben mit dem gleichen problem. Können Sie helfen.
  • Fand ich nie heraus. Wie ich schon in dem Kommentar oben, landete ich jedes video, wenn das scrollen Stoppt.
  • Haben Sie versucht, mit mehreren Spielern, so können Sie Vorspannung videos einfach? Und vielleicht habe ich verpasst, was ist die Größe der Zelle, ist es in den Vollbildmodus?
  • Soweit ich weiß replaceCurrentItemWithPlayerItem ist bereits die Decodierung der video-und zeigt das erste Bild an, auch wenn du nicht spielst das item. Dies scheint zu passieren, auf dem Haupt-thread. Mein Ansatz dafür war nur mit einem einzigen AVPlayer und Befestigung seiner Leistung an den Zellen playerLayers, wenn auch dafür die Tabelle/collectionview super performant (Rastern, keine Ecke, radius -, minimal-offscreen-rendering). Einige Dinge in der UIKit Welt nur passieren, auf dem Haupt-thread, so dass Sie haben, um zu versuchen, um zu halten es frei (am Ende wechselte ich auf ASDK)
  • Wie sind Sie ur reuseIdentifier für die Zelle??? Sie versuchen, es zu bekommen, indem reuseidentifier aber nicht die Einstellung hier?
  • Wie viele Zeilen auf einem Bildschirm für Ihren Fall???weil für jede Zeile intialliase-Methode aufgerufen werden, Können, wenn Sie einen Bildlauf durchführen, wird diese Methode aufgerufen, für mehr als ein Reihen, und das anhalten und das Auswechseln geschieht mehrere Male.

InformationsquelleAutor Sti | 2014-08-17
Schreibe einen Kommentar