11

Swift 2 で、URL からデータを取得し、NSURLSession を使用して JSON オブジェクトとして返す関数を作成したいと考えています。最初は、これはかなり簡単に思えました。私は次のように書いた:

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、完了ブロックの署名を変更せずに完了ブロックに伝播できることはありましたか?

4

3 に答える 3

21

あなたのキャッチは網羅的ではないと思うので、次のようなものが必要です:

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)
}
于 2015-06-15T09:09:55.937 に答える
2

Jguffey からの質問に対処します。次のように関数を呼び出そうとすると、同じエラーが発生しました。

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

次のようになります。

let taskResult = getJson(url!) { 
         (any: AnyObject?,resp: NSURLResponse?,error: NSError?) in
于 2015-08-10T03:53:23.993 に答える
1

NSJSONSerialization は、NSError ではなく ErrorType をスローします。

したがって、正しいコードは次のようになります

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

また、メソッド シグネチャを ErrorType に変更します。

このため、受け入れられた回答は常に「何か他のことが起こった」ブロックに入り、NSJSONSerialization.JSONObjectWithData によってスローされたエラーを報告することはありません。

于 2015-11-09T21:52:37.653 に答える