它有时有效,但有些抛出错误:无法推断通用参数'T' - Swift

Posted

技术标签:

【中文标题】它有时有效,但有些抛出错误:无法推断通用参数\'T\' - Swift【英文标题】:It works sometimes, but some throws error: Generic parameter 'T' could not be inferred - Swift它有时有效,但有些抛出错误:无法推断通用参数'T' - Swift 【发布时间】:2021-12-25 17:15:18 【问题描述】:

直到现在我都没有遇到任何问题,这很奇怪。 Swift 从未抱怨过这段代码。一个用户注册时出错,我调试了一个打印语句,也许是因为代码的自省,现在 swift 捕获了错误并说:

Generic parameter 'T' could not be inferred

我认为这就是您处理延续的方式,我的代码有什么问题? 有趣的是它有时会起作用,有时会抛出上面的错误:/

错误在一行:try await withCheckedThrowingContinuation

这是完整的代码:

// Signup
final func signUp(username: String, email: String, password: String) async throws -> (message: String, didItSucceed: Bool) 
    print("➡️ About to sign up user")
    
    try await withCheckedThrowingContinuation  continuation in
        let userAttributes = [AuthUserAttribute(.email, value: email)]
        let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
        
        _ = Amplify.Auth.signUp(
            username: username,
            password: password,
            options: options
        )  result in
            switch result 
                case .success(let signUpResult):
                    print("✅ Signup confirmed. Next-> needs email verification from \(email)")
                    
                    switch signUpResult.nextStep 
                        case .done:
                            print("✅ Finished sign up!")
                        case .confirmUser(_, _):
                            DispatchQueue.main.async 
                                // Confirm the Auth State to confirm code passing in the username to confirm
                                self.authState = .login
                            
                            continuation.resume(returning: ("Check your Email ????", true))
                    
                case .failure(let error):
                    var errorMessageToTheUser = "Something went wrong ????"
                    print(error)
                    continuation.resume(returning: (errorMessageToTheUser, false))
            
        
    

编辑:

如果我删除 withCheckedThrowingContinuation 顶部的 print(),异常就会消失。但是用户注册时的错误仍然存​​在,并且在行崩溃:

try await withCheckedThrowingContinuation  continuation in

并将(错误)带到@main struct 说:线程1:EXC_BAD_ACCESS (code=1, address=0x46b56a8a6b20)

怎么了?

【问题讨论】:

【参考方案1】:

首先,您应该使用withUnsafeThrowingContinuationChecked 版本仅用于测试您是否正确执行了所有操作;它有你不想遇到的开销,除非你必须这样做。 (但是,正如我们将看到的,您并没有正确地做所有事情,所以这实际上是目前的一个不错的选择!)

其次,如果您查看文档,您会发现这是一个泛型函数,其类型 T 是通过 CheckedContinuation(您的 continuation)的解析来解决的。所以不要仅仅说

continuation in

如有必要,您可以提供类型信息:

(continuation: CheckedContinuation<WhatType, Error>) -> Void in

(我不知道你应该为 WhatType 输入什么类型,因为你没有提供足够的信息。)

第三,您正在崩溃,因为您错误地使用了延续。您必须在实现中每个可能的退出路径上准确调用一次continuation.resume,而您没有这样做(例如查看.done 路径)。我想你会发现,当你解决了这个问题后,其他问题就会迎刃而解。

第四,print 语句改变一切的原因是,在你把它放在那里之前,在你的try await 之前有一个隐含的return。多亏了这一点,编译器才能够推断出有问题的类型。但是,当您添加 print 时,您将其取消了。如果您输入return try await,您的编译问题可能会全部消失(尽管您仍然会崩溃,因为您没有正确使用延续)。

【讨论】:

现在正在读取您的 cmets,我返回的类型在函数上,它将是 (String, Bool) 有趣的是,我很久以前在使用延续时问过,他们告诉我相反,我不应该使用withUnsafeThrowingContinuation。我将如何返回字符串和布尔值?我试过这个:try await withUnsafeThrowingContinuation (continuation: CheckedContinuation&lt;String, Bool, Error&gt;) -&gt; 但不起作用。 好吧,有了你的 cmets,我有点想这就是我让它工作的方式,请检查它是否正确:return try await withUnsafeThrowingContinuation (continuation: UnsafeContinuation&lt;(message: String, didItSucceed: Bool), Error&gt;) -&gt; Void in 编辑:不断抛出错误:/ 你打败了我!很好,但在这样做之前我会三思而后行。请记住,throws 的全部意义在于您通过投掷来表示失败。不需要返回 String-and-a-Bool。要么你返回一个字符串,要么你抛出。所以我会说重新考虑你在这个方法上的整个架构。 它仍然抛出错误:/

以上是关于它有时有效,但有些抛出错误:无法推断通用参数'T' - Swift的主要内容,如果未能解决你的问题,请参考以下文章

应用程序因错误而崩溃:无法推断通用参数“T”

无法推断通用参数“SelectionValue”

无法推断通用参数“D”。 [订购错误]

无法推断类型参数“T”

无法推断通用参数“值”

RxDataSources`无法推断通用参数'Self'`