2016-08-31 9 views
1

Ich bin ziemlich neu in iOS und will und Verwendung von Alamofire. Ich möchte folgende Fragen stellen: Wie man einen Abschlussblock aufruft, wenn alle Elemente (in meinem Fall Benutzer) bereits behandelt werden. Completion-Block ist in defer BlockAlamofire - Wie geht man mit Fertigstellungsblöcken um?

StopsHandler.swift

func requestStopsForUser(user: User, completion: (result: RequestResult, json: JSON?) -> Void) { 
    alamofireManager?.request(.GET, "\(AppSettings.ApiURL)/v1/users/\(user.id)/stops.json", headers: ["Authorization": "Token token=\(user.apiKey)"]).responseJSON { response in 
     switch response.result { 
     case .Success: 
      if let value = response.result.value { 
       completion(result: .Success, json: JSON(value)) 
      } 
     case .Failure(let error): 
      if error.code == NSURLErrorTimedOut { 
       completion(result: .TimedOut, json: nil) 
      } else { 
       completion(result: .ConnectionFailed, json: nil) 
      } 
     } 
    } 
} 

Main.swift

func fetchUsersAndStops(completion: (result: RequestResult) -> Void) { 

    var allStopsToWrite = [[Stop]]() //for each user we have array of stops to write in model 

    requestAllUsers() { result, json in 
     switch result { 
     case .Success: 
      let users = self.usersFromJSON(json) 

      for (i, user) in users.enumerate() { 
       StopsHandler.sharedInstance.requestStopsForUser(user) { result, json in 
        print("i in = \(i)") 
        switch result { 
        case .Success: 
         defer { 
          let isLastUser = (i == users.count - 1) 
          if isLastUser { 
           try! self.realm.write(transactionBlock: { 
            for (index, stopsToWrite) in allStopsToWrite.enumerate() { 
             users[index].stops.appendContentsOf(stopsToWrite) 
             self.realm.add(users[index], update: true) 
            }}, 
            completion: { 
             completion(result: .Success) //I want to call this completion when last user is already handled. 
           }) 
          } 
         } 

         guard let json = json else {return} 
         let stops = StopsHandler.sharedInstance.stopsFromJSON(json) 

         let globalStops = self.realm.objects(Stop) 

         var stopsToWrite = [Stop]() 

         for stop in stops { 
          if globalStops.filter("id = '\(stop.id)'").first == nil { 
           stopsToWrite.append(stop) 
           if let currentUserId = self.currentUser?.id { 
            if currentUserId == user.id { 
             user.loggedIn = true 
            } 
           } 
          } 
         } 
         allStopsToWrite.append(stopsToWrite) 
        case .TimedOut: 
         completion(result: .TimedOut) 
        case .ConnectionFailed: 
         completion(result: .ConnectionFailed) 
        } 
       } 
      } 
     case .TimedOut: 
      completion(result: .TimedOut) 
     case .ConnectionFailed: 
      completion(result: .ConnectionFailed) 
     } 
    } 
} 

Ich gehe davon aus, dass mein Code läuft in main_queue und ich mag die Ausgabe des folgenden (Ich habe 4 Benutzer auf dem Server):

i in = 0 
i in = 1 
i in = 2 
i in = 3 

Aber plötzlich habe ich folgendes:

i in = 3 
i in = 1 
i in = 2 
i in = 0 

Und ich weiß nicht, warum. Jede Hilfe wird massiv geschätzt! Danke im Voraus!

+0

Sie haben 4 Benutzer, also rufen Sie die Anfrage 4 Mal, und Sie möchten etwas tun, nachdem Sie alle 4 Benutzer abgerufen, das ist Ihre Frage? Ziemlich unklar, was Sie wirklich fragen wollen – Tj3n

+0

@ Tj3n ja, das richtige ich möchte etwas tun, nachdem ich alle Benutzer verarbeitet –

+0

haben Sie die Anzahl der Anfrage im Voraus? wie du weißt, dass du es 4 mal anrufen musst? – Tj3n

Antwort

0

Alamofire.request läuft nicht in der Hauptwarteschlange. Es läuft asynchronously, obwohl die .responseJSON standardmäßig auf main queue zurückgegeben wird, damit Sie die Benutzeroberfläche aktualisieren können. Daher ist Ihre Ausgabe nicht das, was Sie erwartet haben.

Wenn Sie möchten, dass es in der Reihenfolge zurückgegeben wird, müssen Sie Ihre Anfrage in eine Dispatch-Hauptwarteschlange schreiben.

Etwas wie folgt aus:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(0.2) * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), { 
    // your code here. 
}) 
0

Als Alarmofire ruft Anfrage in Asynchron-Methode. Das ist der Grund, warum alle Anfragen gleichzeitig angerufen werden, aber die Antwortzeit ist nicht für alle Anfragen gleich.

Um alle Anfragen nacheinander aufzurufen, können Sie den Dienst anrufen, sobald der vorherige Dienst abgeschlossen ist.

Da wir mit demselben Problem konfrontiert sind, haben wir einen dispatch_block_t verwendet, um die Sequenz-Aufgabe auszuführen.

- (void)fetchAllUserAndStopWithCompletion:(void(^)(id resultResponse, BOOL isComplete))completion { 

    // Step 1: Define default parameters and limits. 
    __block NSInteger totalNumberOfUser = 4; 
    __block NSInteger currentRequest = 0; 
    __block dispatch_block_t t_request; 

dispatch_block_t request = [^{ 
    // Step 2: Fetch User information for currentRequest id. 
    [UserRequest fetchUserRequestWithId:<UserId or Any Unique Id> 
          successBlock:^(id resultResponse, NSError *error) { 

           currentRequest += 1; 
           // Step 3: Check for remaining request. If request is remaining then call ’t_request()’. 
           if (currentRequest < totalNumberOfUser) { 
            // Request Remaining 
            if (completion) { 
             id response = (!error)?resultResponse:nil; 
             completion(response, NO); 
            } 
            t_request(); 
           } 
           else { 
            // All Request Completed 
            if (completion) { 
             id response = (!error)?resultResponse:nil; 
             completion(response, YES); 
            } 
           } 
          }]; 

} copy]; 

t_request = request; 
request(); 
} 

Hinweis: Dies hilft nur, wenn Sie jede Benutzerinfo mit einem anderen Anruf abrufen. Wenn Sie alle Benutzerinformationen in einem einzelnen Aufruf erhalten, müssen Sie nur einen Benutzer mit NSSortDescriptor sortieren.

Wenn Sie Probleme bei der Ausführung der Sequenzaufgabe haben, können Sie einen Kommentar hinterlassen.

Verwandte Themen