2013-02-11 5 views
17

Wie der Titel impliziert, aktualisiert und UICollectionView nicht anzeigt die Zellen sofort nach dem Aufruf reloadData. Stattdessen scheint es meine Sammlung nach 30 bis 60 Sekunden zu aktualisieren. Mein Setup ist wie folgt:UICollectionView wird nicht sofort beim Aufrufen von reloadData aktualisiert, aber nach dem Zufallsprinzip nach 30 bis 60 Sekunden

UICollectionView hinzugefügt Controller in der Storyboard anzuzeigen sowohl mit delegate und dataSource Setup für den View-Controller und Standard-Steckdose Setup numberOfSectionsInRow & cellForItemAtIndexPath beiden implementiert werden und verweisen auf die prototypisiert Zelle und die imageView in der es

Hier ist der Code, der zu Twitter geht, eine Zeitleiste erhält, einer Variablen zuordnet, eine Tabellenansicht mit den Tweets neu lädt und dann die Tweets durchsucht, um Fotos zu finden und die Sammlungsansicht mit diesen Elementen neu zu laden.

Auch wenn ich den Code auskomme, um das Bild anzuzeigen, ändert es nichts.

SLRequest *timelineRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:timelineURL parameters:timelineParams]; 
[timelineRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) { 
    if(responseData) { 
     JSONDecoder *decoder = [[JSONDecoder alloc] init]; 

     NSArray *timeline = [decoder objectWithData:responseData]; 

     [self setTwitterTableData:timeline]; 

     for(NSDictionary *tweet in [self twitterTableData]) { 
      if(![tweet valueForKeyPath:@"entities.media"]) { continue; } 

      for(NSDictionary *photo in [[tweet objectForKey:@"entities"] objectForKey:@"media"]) { 
       [[self photoStreamArray] addObject:[NSDictionary dictionaryWithObjectsAndKeys: 
                [photo objectForKey:@"media_url"], @"url", 
                [NSValue valueWithCGSize:CGSizeMake([[photo valueForKeyPath:@"sizes.large.w"] floatValue], [[photo valueForKeyPath:@"sizes.large.h"] floatValue])], @"size" 
                , nil]]; 
      } 
     } 

     [[self photoStreamCollectionView] reloadData]; 
    } 
}]; 
+0

Sind Sie sicher, dass dies, weil Sie nicht nicht nur ist sind Aufruf von -reloadData, bis die Anfrage abgeschlossen ist? (Das braucht Zeit). – indragie

Antwort

41

Dies ist ein klassisches Symptom UIKit Methoden aus einem Hintergrundthread zu nennen. Wenn Sie die -[SLRequest performRequestWithHandler:] documentation anzeigen, sagt es, dass der Handler keine Garantie gibt, auf welchem ​​Thread es ausgeführt wird.

Wickeln Sie Ihren Anruf zu reloadData in einem Block und übergeben Sie dies an dispatch_async(); übergeben Sie auch dispatch_get_main_queue() als Warteschlangenargument.

+0

Sie gewinnen! Den Code genau so zu verpacken, wie du es gesagt hast, behebt das Problem. Gibt es einen grundlegenden Unterschied zwischen UITableView und UICollectionView, die reloadData auf UITableView aber nicht UICollectionView arbeiten lassen? – nullfox

+0

@nullfox froh, dass es funktioniert hat! Mir ist kein Unterschied bekannt, aber wenn es einen gibt, ist es wahrscheinlich, dass Implementierungsdetails nicht verlässlich sind. Die einzige Vorgehensweise besteht darin, sicherzustellen, dass an ein UIKit-Objekt gesendete Nachrichten an den Hauptthread gesendet werden. –

+0

Stunden Debugging mit Ihrer einfachen Lösung gelöst! Dasselbe Problem betrifft übrigens UITableView. Vielen Dank! – RyJ

3

Apple sagen: Sie sollten diese Methode nicht inmitten von Animationsblöcken aufrufen, in die Elemente eingefügt oder gelöscht werden. Durch Einfügen und Löschen werden die Daten der Tabelle automatisch entsprechend aktualisiert.

Im Gesicht: Sie sollten diese Methode nicht mitten in einer Animation aufrufen (UICollectionView im Scrolling einschließen).

so können Sie:

[self.collectionView setContentOffset:CGPointZero animated:NO]; 
[self.collectionView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; 

oder sicher markieren keine Animation, und dann reload nennen; oder

[self.collectionView performBatchUpdates:^{ 
//insert, delete, reload, or move operations 
} completion:nil]; 
7

Sie müssen das Update auf den Hauptthread Versandfertig:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.photoStreamCollectionView reloadData]; 
    }); 

oder in Swift:

dispatch_async(dispatch_get_main_queue(), { 
    self.photoStreamCollectionView.reloadData() 
}) 
+0

Dies ist ein Duplikat der angenommenen Antwort ... – JAL

Verwandte Themen