Неблокирующее соединение Alamofire

Я использую Alamofire для базовой сети. Вот моя проблема. у меня есть класс

class User {
    var name:String?
    var company:String

init () {
  //
   manager = Alamofire.Manager(configuration: configuration)
  }

 func details () {
    //first we login, if login is successful we fetch the result

 manager.customPostWithHeaders(customURL!, data: parameter, headers: header)
          .responseJSON { (req, res, json, error) in
              if(error != nil) {
                  NSLog("Error: \(error)")
            }
             else {
                 NSLog("Success: \(self.customURL)")
                 var json = JSON(json!)
                 println(json)
                     self.fetch()
                      println("I fetched correctly")
                 }
   }

func fetch() {

   manager.customPostWithHeaders(customURL!, data: parameter, headers: header)

            .responseJSON { (req, res, json, error) in
                if(error != nil) {
                    NSLog("Error: \(error)")
                }
                else {
                    NSLog("Success: \(self.customURL)")
                    var json = JSON(json!)
                    println(json)
            //set name and company
      }
   }
}

Моя проблема в том, что если я сделаю что-то вроде

var my user = User()
user.fetch()
println("Username is \(user.name)")

Я ничего не получаю в консоли для user.name. Однако, если я поставлю точку останова, я увижу, что правильно получаю имя пользователя и компанию внутри своей функции выборки. Я думаю, что менеджер работает в отдельном неблокирующем потоке и не ждет. Однако я действительно не знаю, как я могу инициализировать свой класс с правильными данными, если я не могу знать, успешно ли завершился менеджер. Итак, как я могу правильно инициализировать свой класс для немедленного доступа после того, как все потоки менеджера Alamofire выполнили свою работу?


person Meanteacher    schedule 10.03.2015    source источник


Ответы (1)


Вы не хотите создавать сеть внутри объекта вашей модели. Вместо этого вы хотите обрабатывать сетевой уровень в каком-то более абстрактном объекте, таком как Service методов класса. Это всего лишь простой пример, но я думаю, что он поможет вам двигаться в гораздо лучшем архитектурном направлении.

import Alamofire

struct User {
    let name: String
    let companyName: String
}

class UserService {

    typealias UserCompletionHandler = (User?, NSError?) -> Void

    class func getUser(completionHandler: UserCompletionHandler) {
        let loginRequest = Alamofire.request(.GET, "login/url")
        loginRequest.responseJSON { request, response, json, error in
            if let error = error {
                completionHandler(nil, error)
            } else {
                println("Login Succeeded!")

                let userRequest = Alamofire.request(.GET, "user/url")
                userRequest.responseJSON { request, response, json, error in
                    if let error = error {
                        completionHandler(nil, error)
                    } else {
                        let jsonDictionary = json as [String: AnyObject]
                        let user = User(
                            name: jsonDictionary["name"]! as String,
                            companyName: jsonDictionary["companyName"]! as String
                        )

                        completionHandler(user, nil)
                    }
                }
            }
        }
    }
}

UserService.getUser { user, error in
    if let user = user {
        // do something awesome with my new user
        println(user)
    } else {
        // figure out how to handle the error
        println(error)
    }
}

Поскольку и вход в систему, и пользовательские запросы являются асинхронными, вы не можете начать использовать объект User, пока оба запроса не будут выполнены и у вас не будет допустимого объекта User. Замыкания — отличный способ зафиксировать логику для запуска после завершения асинхронных задач. Вот еще несколько тем по Alamofire и асинхронным сетям, которые также могут вам помочь.

Надеюсь, это прольет свет.

person cnoon    schedule 11.03.2015
comment
Спасибо за хорошее объяснение и предложения. Как вы предложили, я перенесу свой сетевой код в другой класс и назову его, как вы предложили. Я очень ценю, что вы тратите свое время, чтобы объяснить мне это. - person Meanteacher; 11.03.2015
comment
Нет проблем... рад помочь! - person cnoon; 11.03.2015