Подтвердить что ты не робот

В Swift 2, как я могу вернуть JSON ошибки синтаксического анализа в блок завершения?

Я хотел бы создать функцию в Swift 2, которая получает данные из URL-адреса и возвращает его как объект JSON, используя NSURLSession. Сначала это выглядело довольно прямолинейно. Я написал следующее:

func getJson(url:NSURL, completeWith: (AnyObject?,NSURLResponse?,NSError?)->Void) -> NSURLSessionTask? {

    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithURL(url) {
        (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in

        if error != nil {
            completeWith(nil, response, error)
        }

        if let data = data {

            do {
                let object:AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
            } catch let caught as NSError {
                completeWith(nil, response, caught)
            }

            completeWith(object, response, nil)

        } else {
            completeWith(nil, response, error)
        }
    }

    return task
}

Однако это не скомпилируется, потому что блок завершения не объявляет "броски". Точная ошибка Cannot invoke 'dataTaskWithURL' with an argument list of type '(NSURL, (NSData?, NSURLResponse?, NSError?) throws -> Void)'. Несмотря на то, что я обнаружил все ошибки в своем выражении do/catch, Swift по-прежнему хочет распространять NSError в цепочке. Единственный способ, который я вижу вокруг, - использовать try!, например:

if let data = data {

    let object:AnyObject? = try! NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
    completeWith(object, response, nil)

} else {
    completeWith(nil, response, error)
}

Теперь все компилируется просто отлично, но я потерял NSError, который был добавлен NSJSONSerialization.JSONObjectWithData.

Я могу захватить NSError, потенциально выброшенным NSJSONSerialization.JSONObjectWithData, и передать его в блок завершения без изменения сигнатуры блока завершения?

4b9b3361

Ответ 1

Я думаю, ваш улов не исчерпывающий, поэтому вам нужно что-то вроде этого:

do
{
  let object:AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
  completeWith(object, response, nil)
} catch let caught as NSError {
  completeWith(nil, response, caught)
} catch {
  // Something else happened.
  // Insert your domain, code, etc. when constructing the error.
  let error: NSError = NSError(domain: "<Your domain>", code: 1, userInfo: nil)
  completeWith(nil, nil, error)
}

Ответ 2

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

let taskResult = getJson(url!) { 
     (any: AnyObject,resp: NSURLResponse,error: NSError) in

он должен выглядеть следующим образом:

let taskResult = getJson(url!) { 
         (any: AnyObject?,resp: NSURLResponse?,error: NSError?) in

Ответ 3

NSJSONSerialization выбрасывает тип ErrorType, а не NSError.

поэтому правильный код будет

do {
    let object:AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
} catch let caught as ErrorType {
    completeWith(nil, response, caught)
}

Вы также меняете свою подпись метода на ErrorType.

По этой причине принятый ответ всегда войдет в блок "что-то еще случилось" и никогда не сообщит об ошибке, вызванной NSJSONSerialization.JSONObjectWithData.