2016-05-16 4 views
0

Ich verwende den folgenden Code zu führen, was ich eine Hintergrundsynchronisation sein möchte, aber der Haupt-Thread verlangsamt oder sogar zum Stillstand kommt, wenn der Json empfangen ist größer als 20 oder also Aufzeichnungen. Gibt es etwas Falsches an diesem Code für eine Hintergrundoperation? Was könnte den Hauptthread blockieren? Vielen Dank für Anregungen.IOS: Haupt-Thread verlangsamt während Hintergrund-Betrieb

Hinweis: Es gibt eine auskommentierte Zeile unterhalb von performSelectorOnMainThread, wo die App die JSON-Verarbeitung verarbeitet, die ich in einen weiteren Hintergrund-Thread geändert habe, aber die Änderung scheint nicht zu helfen.

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1 
#define kProductsURL [NSURL URLWithString: @"http://~/getproducts.php"] 

//in viewDidLoad 
if(hasInternet==YES && [loggedIntoServer isEqual:@1]) { 

     dispatch_async(kBgQueue, ^{ 
      NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 
       //previous line grabed data from api. 
      if (data) { 
     // [self performSelectorOnMainThread:@selector(fetchData:) withObject:data waitUntilDone:YES];//no longer doing this on main thread 
       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
        [self fetchData:data]; 
       }); 

       } 
     }); 
       ; 
    } //close hasInternet, logged into server. 



    - (void)fetchData:(NSData *)jsonFeed { 
    NSError* error; 
    NSDictionary* json = [NSJSONSerialization JSONObjectWithData:jsonFeed 
                 options:kNilOptions 
                  error:&error]; 
    NSMutableArray* latestProducts = [[NSMutableArray alloc] init]; 
    //this is specific to format of JSON 
    if (![[json objectForKey:@“products"] isKindOfClass:[NSNull class]]) { 
      latestProducts = [[json objectForKey:@“products"]mutableCopy]; 
    getProducts = latestProducts; 
    int size = [latestProducts count]; 
    [self.tableView reloadData]; 
    getProducts = [self convertFeedtoObject:latestProducts]; 
    [self importAndSaveProducts:getProducts];//this imports and saves 
    self.recentlySynced=YES; 
    } 
} 
+0

wo ist das Hauptgewinde? –

+0

dispatch_get_global_queue ist kein Hauptthread !!! –

+0

Ich bin neugierig, was Ihre 'fetchData:' Methode tut. Und wie Sie 'kBgQueue' erstellen – marosoaie

Antwort

1

Sie haben gerade etwas überflüssig gemacht. Sie haben das Abrufen von Daten in einem Hintergrundthread ausgelöst. Aber dann hast du auch den [self.tableView reloadData]; im Hintergrund Thread. Aus diesem Grund ist Ihre Benutzeroberfläche betroffen.

Versuchen Sie folgendes:

if(hasInternet==YES && [loggedIntoServer isEqual:@1]) 
{ 
    dispatch_async(kBgQueue,^
    { 
     NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 

     if (data) 
     { 
       dispatch_async(dispatch_get_main_queue(),^
       { 
        [self fetchData:data]; 
       }); 
     } 
    }); 
} 

Was ich getan habe ist ich diesen Teil des Codes geändert:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
        [self fetchData:data]; 
       }); 

Da Sie nur Änderungen in der Haupt-Thread UI tun sollten. und dieser Teil meines Codes erledigt den Job im Hauptthread.

dispatch_async(dispatch_get_main_queue(),^
        { 
         [self fetchData:data]; 
        }); 
+0

Ich habe dieses Recht markiert, weil es sich auf das Nachladen von Daten im Hintergrund-Thread konzentrierte, was das Problem war. Es gab keinen Grund, Daten hier neu zu laden, da das erneute Laden nicht bis zum Ende stattfinden sollte, wenn alle neuen Daten heruntergeladen und analysiert wurden. Ich wählte auch einige der anderen Antworten, die darauf hinwiesen, dass Daten holen (die die Daten analysieren, aber nicht sofort die Benutzeroberfläche beeinflussen) im selben Thread sein sollten. – zztop

1

Sie brauchen keinen verschachtelten Anruf in derselben Warteschlange. Sie sollten auch alle UI-Arbeiten am Hauptthread ausführen. Weitere Informationen finden Sie unter Apples Concurrency Programming Guide

Laden Sie Ihre Tabelle in Ihrer fetchData-Methode wie folgt.

dispatch_async(dispatch_get_main_queue(), { 
    // Your UI work 
    [self.tableView reloadData]; 

}) 


// Remove second dispatch_async call 

//in viewDidLoad 
if(hasInternet==YES && [loggedIntoServer isEqual:@1]) { 

     dispatch_async(kBgQueue, ^{ 
      NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 
       //previous line grabed data from api. 
      if (data) { 
       [self fetchData:data]; 

       } 
     }); 
       ; 
} //close hasInternet, logged into server. 
1

Es gibt mehrere Fehler in Ihrem ursprünglichen Code, wechseln Sie in das folgende:

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) //CHANGE TO BACKGROUND 
#define kProductsURL [NSURL URLWithString: @"http://~/getproducts.php"] 

//in viewDidLoad 
if(hasInternet==YES && [loggedIntoServer isEqual:@1]) { 
     dispatch_async(kBgQueue, ^{ 
      NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 
      if (data) {    
       [self fetchData:data]; 
      } 
     }); 
    } //close hasInternet, logged into server. 

Ändern Sie den Abrufdaten auf die folgenden:

- (void)fetchData:(NSData *)jsonFeed { 
    NSError* error; 
    NSDictionary* json = [NSJSONSerialization JSONObjectWithData:jsonFeed 
                 options:kNilOptions 
                  error:&error]; 

    NSMutableArray* latestProducts = [[NSMutableArray alloc] init]; 

    //this is specific to format of JSON 
    if (![[json objectForKey:@"products"] isKindOfClass:[NSNull class]]) { 

     latestProducts = [[json objectForKey:@"products"]mutableCopy]; 

     getProducts = latestProducts; 
     int size = [latestProducts count]; 

     //Do this on the main thread: 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self.tableView reloadData]; 
     }); 

     getProducts = [self convertFeedtoObject:latestProducts]; 
     [self importAndSaveProducts:getProducts];//this imports and saves 
     self.recentlySynced=YES; 
    } 
} 

Je nachdem, wie der Tabellenansicht Arbeiten und wie die Datenquelle aussieht, möchten Sie möglicherweise die Reload-Tabellenansichtszeile (mit dem Hauptwarteschlangenversand) nach unterhalb von self.recentSynced = YES verschieben.

Verwandte Themen