2016-04-24 2 views
0

Ich versuche, Fotos in Core Data zu laden, aber dies erfordert einige Hintergrundthreads, so dass mein Objekt in Core Data ohne sein Foto gespeichert wird, bekomme ich, dass das Foto Null ist. Und das Gleiche passiert mit den Fotos meiner Gruppen.Führen Sie alle Hintergrundthreads aus, bevor Sie einen anderen Block ausführen

Kurz gesagt, ich speichere bei jeder Iteration ein Objekt in Core Data und das Speichern geschieht schneller als das Laden meiner Fotodaten.

Ich versuchte Semaphors, Barrieren, Gruppen, ... aber keine funktionierte. Ich mache sicherlich etwas falsch, aber ich weiß nicht was. Wenn jemand mir helfen könnte, würde ich es sehr schätzen, es war 2 Wochen, in denen ich mit dem gleichen Problem kämpfe. Dies ist mein Code in einer vereinfachten Version, die Vollversion ist erreichbar unter:

// MARK - ViewDidLoad 
override func viewDidLoad() { 
    // This method is only called once, so you want to create any controls or arrays here 
    super.viewDidLoad() 

    // Verifying connectivity to internet 
    if Reachability.isConnectedToNetwork() == true { 

    // Getting data from Parse + getDataInBackgroundWithBlock 

    }else{ 

    } 
} 


// MARK - Action of the login button 
@IBAction func loginBtn_click(sender: AnyObject) { 
    if usernameTxt.text == "" || passwordTxt.text == "" { 
     self.displayAlert("Error", message: "Please enter a username and password") 
    }else{ 

     // MARK - Login the user 
     PFUser.logInWithUsernameInBackground(usernameTxt.text!, password: passwordTxt.text!) { (user, error) -> Void in 

      if error == nil { 

       let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT) 

       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithAscendingOrder("Add", key: "user", value: userName, ascendingOrder: "added", completionHandler: { (objects1) -> Void in 

       // Update of an array in background 

        }) 
       }) 



       dispatch_async(queue, {() -> Void in 

       // Update of an array in background 

       }) 



       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithAscendingOrder("Group", key: "membersUsername", value: userName, ascendingOrder: "membersUsername", completionHandler: { (objects3) -> Void in 

       // Update of an array in background 

         // MARK - Adding all the users in Core data 
         for var i = 0; i < usersFromParseDataBase.count; i++ { 

          let entity = NSEntityDescription.entityForName("Users", inManagedObjectContext: self.managedObjectContext) 
          let newUser = Users(entity: entity!, insertIntoManagedObjectContext: self.managedObjectContext) 
          if self.arrayAddedUsers.contains(usersFromParseDataBase[i].username){ 

       // Saving new records in Core Data     

          } 
         } 
        }) 
       }) 

       dispatch_async(queue, {() -> Void in 
        self.getObjectsFromQueryWithDescendingOrder("Group", key: "membersUsername", value: userName, descendingOrder: "conversationUpdate", completionHandler: { (objects4) -> Void in 

          if array.count == 2 { 

        // Getting data in background - photo.getDataInbackgroundWithBlock     

           } 
          }else{ 

       // Getting data in background - photo.getDataInbackgroundWithBlock 

          } 
         } 
        }) 
       }) 

       dispatch_barrier_async(queue, {() -> Void in 

     // Doing some stuff in background which needs the data from threads above 

       }) 

      }else{ 
       // Print error from loginWithUsernaemInBackground 
      } 
     } 
    } 
} 

Dies ist, was in das Protokoll angezeigt wird, so dass man deutlich sehen kann, dass die Barriere vor dem Laden von Bildern ausgeführt wird erfolgt die Ausführung .

TEST 3 - interacting user has been saved to core data 
Loading profile image 
Loading profile image 
Loading group image 
Loading profile image 
Loading profile image 
9 
5 
Loading group image 
Loading group image 
Loading group image 
Loading group image 

Die Sache ist, dass ich diese Daten für andere Operationen später benötigen. Mein Code ist nicht konsistent.

+1

können Sie sich dispatch_group_create(), dispatch_group_wait() und dispatch_group_async() ansehen, um eine Gruppe von Aufgaben zu haben, auf die Sie warten müssen, bevor Sie fortfahren. Dieser Link könnte helfen: http://stackoverflow.com/questions/11909629/waiting-until-two-async-blocks-are-executed-before-starting-another-block –

+0

Wenn die Code-Blöcke, die Sie versenden, sind, selbst, asynchrone Aufgaben, müssen Sie explizit explizit "dispatch_group_enter"/"leave". Es wird schwierig sein, Ihr Problem zu diagnostizieren oder weiter zu beraten, ohne den Code zu sehen, der diese Protokollnachrichten generiert. Oder, um ehrlich zu sein, weil Ihr Code so kompliziert ist, möchten Sie vielleicht [ein viel einfacheres, reproduzierbares Beispiel] (http://stackoverflow.com/help/mcve) konstruieren, das die Art des Fehlers beschreibt, den Sie beschreiben. – Rob

+0

Hallo Rob, ich habe eine einfachere Version meines Codes mit nur den wichtigsten Teilen hinzugefügt. Ist es umfassend? Wenn nicht, kann ich versuchen, es einfacher zu machen. Danke für Ihre Hilfe. dee zg, ich habe es bereits versucht dispatch_group_create() ... aber ich habe immer noch das selbe Problem. Es ist nur so, dass ich nicht weiß, wie ich es richtig umsetzen soll. Ich bekomme immer das gleiche Problem, wenn ich "Sleep (Uint32)" zu meinem letzten Block hinzufügen, aber das ist nicht konsistent. – C00kieMonsta

Antwort

-1

Ich denke, Sie sind auf dem richtigen Weg. Wenn ich ein einfaches Programm erstellen und verwenden dispatch_barrier_async es funktioniert perfekt:

let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT) 

dispatch_async(queue, {() -> Void in 
    sleep(1) 
    print("1") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(2) 
    print("2") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(3) 
    print("3") 
}) 

dispatch_async(queue, {() -> Void in 
    sleep(4) 
    print("4") 
}) 

dispatch_barrier_async(queue, {() -> Void in 
    print("done") 
}) 

Ausgang:

1 
2 
3 
4 
done 

ich glaube, das Problem ist, dass dispatch_async nicht für den Anruf nicht warten, bis PFFile.getDataInBackgroundWithBlock zu beenden:

Versuchen Sie alle Anrufe zu getDataInBackgroundWithBlock mit dem synchronen Aufruf zu PFFile.getData (https://parse.com/docs/osx/api/Categories/PFFile%28Synchronous%29.html#/c:objc%28cs%29PFFile%28im%29getData :) statt:

var imageData = photoFile.getData 
if (imageData != nil) { 
    self.arrayImageFiles.append(imageData!) 
} 

Dies sollte wirklich keine Performance-Probleme haben, da Sie bereits diesen Code asynchron ausgeführt werden.

+0

Vielen Dank für Ihre Antwort. Ich muss noch einige Tests machen, aber das könnte mir helfen.Ich wusste nicht, dass es möglich ist, die Bilddaten im Hauptthread zu laden. Ich schätze Ihre Hilfe sehr und werde Sie auf dem Laufenden halten, wenn sie mein Problem wirklich löst. – C00kieMonsta

+0

Die Verwendung von "dispatch_barrier_async" _kann nur als "Sentinel" verwendet werden, wenn die zuvor in derselben Warteschlange übertragenen Aufgaben _synchronous_ sind. Im OP-Fall sind sie jedoch asynchron. Das heißt, der Aufruf gibt _immediately_ zurück und - für die Warteschlange - wurde dieser Block beendet. – CouchDeveloper

+0

@CouchDeveloper Dies ist, was ich in meiner Antwort gesagt habe und warum ich empfohlen habe, diese Aufgaben synchron zu machen. Fehle ich etwas? – markwatsonatx

Verwandte Themen