调用可以抛出,但没有标记为'try',错误没有被处理/条件绑定的Initializer必须是Optional类型,而不是'JSON'

Call can throw, but it is not marked with 'try' and the error is not handled / Initializer for conditional binding must have Optional type, not 'JSON'

Sup,各位...我希望你们一切都好。好吧,我编写代码的时间很短,遇到了这个错误,有人知道如何解决吗?目的是让 'file' 即 'Auth Service',当用户向此聊天应用程序提供所有信息时与 'user data service' 进行通信。

我上传的第三张图片是我被教做的。*

AF.request(URL_USER_ADD, method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in

  switch response.result {
          case .success(let result):
             if let json = result as? Data {
                guard let data = response.data else { return }
                guard let json = JSON(data: data) else { return }
                let id = json["_id"].stringValue
                let color = json["avatarColor"].stringValue
                let avatarName = json["avatarName"].stringValue
                let email = json["email"].stringValue
                let name = json["name"].stringValue
             }

            case .failure(let result):
                completion(false)
                debugPrint(response.result as Any)

                UserDataService.instance.setUserData(id: _id, color: avatarColor, avatarName: avatarName, email: email, name: name)
                completion(true)
            }
        }
    }
}

error01

error02

lesson taught

似乎 JSON 初始化器 throws,因此编译器告诉您需要处理它。

您还试图访问在该块外的 .success 代码块中声明的局部变量,因此它们是未知的。 id 变量的名称也有误。

AF.request(URL_USER_ADD, method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in

  switch response.result {
          case .success(let result):
             if let json = result as? Data {
                guard let data = response.data else { return }
                do {
                    let json = try JSON(data: data)
                    let id = json["_id"].stringValue
                    let color = json["avatarColor"].stringValue
                    let avatarName = json["avatarName"].stringValue
                    let email = json["email"].stringValue
                    let name = json["name"].stringValue
                    UserDataService.instance.setUserData(id: id, color: avatarColor, avatarName: avatarName, email: email, name: name)
                    completion(true)
                } catch {
                    print(error)
                    completion(false)
                }
            }

            case .failure(let result):
                completion(false)
                debugPrint(response.result as Any)
            }
        }
    }
}

作为一种风格,简单的 returns truefalse 的完成处理程序并不是特别有用,因为它不提供有关 [=24= 的任何信息]当返回 false 时, 出错了,但既然你提到了一个教训,我会假设这不是你的设计选择。

这段代码似乎是流行编程课程的一部分,因为我回答了 another post

您老师的代码是错误的,因为它没有处理 JSON 的抛出初始化程序。也许它适用于某些早期版本的 SwiftyJSON。在任何情况下,@Paulw1 的回答都能帮助您完成大部分工作。问题是,如果周围的函数没有标记为 throws,那么简单地调用 try JSON(data: data) 将是一个问题。鉴于您已经解决了一些其他错误(例如未能打开可选值),这显然是可以接受的,因为这是您老师的代码所做的,您可以这样做:

guard let json = try? JSON(data: data) else { return }

这是 try 及其变体的优惠。

try

对于 try,要么周围的函数必须标记为 throws,在这种情况下,抛出的任何错误都会传播到调用者,或者您必须在 do...catch.

因此,如果我们假设您的函数名为 foo,则需要声明如下:

 func foo(...) throws -> ReturnTypeIfAny

或者您必须像这样将 try 包裹在 do...catch 中:

let json: JSON
do {
    json = try JSON(data: data)
}
catch {
    // do something with the error
}

try?

try? returns nil 如果能扔的东西确实扔了。所以你可以像处理任何可选的 return 类型一样处理它。

guard let json = try? JSON(data: data) else { return }

if let json = try? JSON(data: data)
{
   // code that access json goes here
}

try!

大多数时候你可能想避免这个。 try! 完全忽略了抛出错误的可能性,抛出一个就崩溃。当您确定即使您调用的函数被标记为 throws,您也知道它实际上不能 throw.[= 时,请仅使用它 38=]

当它被标记为 throws 的原因时可能会发生这种情况,因为它是 protocol 一致性的一部分,但你调用的东西是你写的东西,在你的情况下,你知道它永远不会抛出。在那种情况下 try! 是可以的。但是,如果您调用的不是您的代码,或者您有疑问,请始终假设任何标记为 throws 的函数实际上都可以抛出异常,因此您需要处理它。