2015-08-18 3 views
1

Я пытаюсь создать функцию, которая возвращает NSDictionary, который в свою очередь должен быть возвращен из закрытия.SWIFT: Передача переменной от закрытия к функции

Я относительно новичок в Swift, и у меня проблемы с этим. Любая помощь будет принята с благодарностью.

// Takes a String, needs to return a NSDictionary 

func login(action: String) -> NSDictionary 
{ 
    let command = NSURL(string: "\(connectionType)://\(url)/includes/api.php?username=\(username)&password=\(password)&accesskey=\(apiKey)&action=\(action)&responsetype=json") 
    print(command!) 

    let session = NSURLSession.sharedSession() 

    // Get error here when changing Void > NSDictionary 
    let task = session.dataTaskWithURL(command!) { 
     (data, response, error) -> Void in 

     if error != nil { 

      print(error!.localizedDescription) 

     } else { 

      do { 
       let result = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSDictionary 

       print(result) // Need this returned 

      } catch { 
       // handle error 
       print(error) 
      } 
     } 
    } 

    task.resume() 

    return result As! NSDictionary // returns empty, because of -> Void?? 

} 
+0

То, что вы пытаетесь сделать, невозможно. 'result' еще не существует, поскольку он еще не создан. 'NSURLSession' займет некоторое время, чтобы загрузить данные JSON (это может занять несколько минут), и только после этого вы сможете получить доступ к значению результата. –

ответ

2

Проблема заключается в том dataTaskWithURL является асинхронной функцией, поэтому она hasnt удосужился выполнение блока еще до возвращения функции.

Что нужно сделать, это либо установить функцию, которая может быть вызвана на self, которая будет знать, когда блок выполнен и может передать вам результат, или настроить протокол с делегатом, который вы можете позвонить, чтобы уведомить от результата

также, -> Void внутри блока является типом возврата блока, вы все равно ничего не должны возвращать внутри этого блока, потому что с ним ничего не произойдет, поскольку родительская функция не ожидает, что что-либо будет возвращено, следовательно, почему его Void

2

В вашем заявлении типа закрытия

let task = session.dataTaskWithURL(command!) { 
    (data, response, error) -> Void in 
    /* closure body */ 
} 

изменить Void к JSONObject. Но это не все! Вы пытаетесь вернуть что-то из функции входа, которая делает асинхронный вызов, и это невозможно. Вместо этого, ваша функция login должна принять закрытие, и это закрытие будет там, где вы что-то делаете с результатом NSDictionary. Таким образом, изменить свою декларацию login в

func login(action: String, completionHandler: (NSDictionary) ->()) 

и осуществлять completionHandler соответственно.

+1

Первая часть вашего ответа не будет работать. Метод 'dataTaskWithURL' ожидает, что обработчик завершения вернет' Void', и попытка его изменения просто вызовет ошибку компилятора. – JeremyP