Swift - 传递多个闭包参数时不应使用尾随闭包语法 [duplicate]

Swift - Trailing closure syntax should not be used when passing more than one closure argument [duplicate]

提问人:rainerwolfram 提问时间:5/27/2022 最后编辑:Robrainerwolfram 更新时间:5/28/2022 访问量:4665

问:

我是 Swift 的新手,并且收到一个带有尾随闭包违规的多个闭包:...来自 SwiftLint 的警告。导致这种情况的代码如下所示。关于我如何重构我的代码以使其不违反 SwiftLint 的任何想法。非常感谢您的帮助

let RepaymentCoordinator = PayCoordinator(
    deLinkedErrorCompletion: { topvc, account in
        self.delinkedErrorCompletion(topvc, account: account)
    }
) { [weak self] _, isPayNowCallCompleted in
    guard let self = self else { return }
    if self.accountDetailsCoordinator != nil, isPayNowCallCompleted {
        self.accountDetailsCoordinator?.reloadBuyNowPayLaterAccountDetails()
    }
}

这:PayCoordinator.init

public init(
    topViewController: UIViewController,
    repaymentProvider: BuyNowPayLaterRepaymentProvidable,
    deLinkedErrorCompletion: @escaping BuyNowPayLaterRepaymentCoordinatorDeLinkedErrorCompletion,
    flowDidFinishCompletion: @escaping BuyNowPayLaterRepaymentCoordinatorFlowDidFinishCompletion
) {
    self.topViewController = topViewController
    self.repaymentProvider = repaymentProvider
    self.deLinkedErrorCompletion = deLinkedErrorCompletion
    self.flowDidFinishCompletion = flowDidFinishCompletion
    super.init()
}
iOS Swift 关闭

评论

0赞 Paulw11 5/27/2022
将尾随闭包更改为命名参数,如deLinkedErrorCompletion
0赞 rainerwolfram 5/27/2022
感谢您的回复。你能给我看看这个吗,我试过这个,但似乎做对了。非常感谢
0赞 Paulw11 5/27/2022
尾随闭包的参数名称是什么?声明是什么样子的?PayCoordinator.init
0赞 rainerwolfram 5/27/2022
public init( topViewController: UIViewController, repaymentProvider: BuyNowPayLaterRepaymentProvidable, deLinkedErrorCompletion: @escaping BuyNowPayLaterRepaymentCoordinatorDeLinkedErrorCompletion, flowDidFinishCompletion: @escaping BuyNowPayLaterRepaymentCoordinatorFlowDidFinishCompletion ) { self.topViewController = topViewController self.repaymentProvider = repaymentProvider self.deLinkedErrorCompletion = deLinkedErrorCompletion self.flowDidFinishCompletion = flowDidFinishCompletion super.init() }
0赞 Vadim Belyaev 5/27/2022
如您所知,SwiftLint 有一个不错的规则文档。单击您感兴趣的规则,您将看到一个页面,其中包含说明和示例(触发和非触发)。

答:

3赞 Rob 5/27/2022 #1

请参阅 SE-0279 了解处理多个闭包时的现代语法。这在《The Swift Programming Language: Closures: Trailing Closures》一书中得到了重申,其中对这一新约定的总结如下:

如果一个函数采用多个闭包,则省略第一个尾随闭包的参数标签,并标记剩余的尾随闭包。

就您而言,您在评论中提供的方法有两个您在问题中没有提供的参数,但我假设您为了简洁起见省略了它们。但是将它们加回去,SE-0279 将指示以下情况之一:init

let coordinator = PayCoordinator(topViewController: topVC, repaymentProvider: provider) { topVC, account in 
    // ...
} flowDidFinishCompletion: { [weak self] _, isCompleted in 
    // ...
}

请注意,前面没有逗号。flowDidFinishCompletion

或者,或者:

let coordinator = PayCoordinator(
    topViewController: topVC, 
    repaymentProvider: provider
) { topVC, account in 
    // ...
} flowDidFinishCompletion: { [weak self] _, isCompleted in 
    // ...
}

为了完整起见,如果只是完全避免尾随闭包语法,并在两个闭包上使用标签,也可以使错误静音。例如,

let coordinator = PayCoordinator(
    topViewController: topVC, 
    repaymentProvider: provider,
    deLinkedErrorCompletion: { topVC, account in 
        // ...
    },
    flowDidFinishCompletion: { [weak self] _, isCompleted in 
        // ...
    }
)

在大多数情况下,SE-0279 语法(如上文 The Swift 编程语言中所重申的)通常是可取的,因为第一个闭包的功能意图通常非常明确。但是,在这种情况下,两个闭包的功能意图并不完全明显,因此也许有必要更明确地标记两个闭包(并且根本不使用尾随闭包语法)。让生成的代码的可读性决定您采用哪种模式。但在所有条件相同的情况下,SE-0279 模式,不标记第一个尾随闭合,是新的约定。

但是,无论哪种方式,上述任何一种都可以避免 SwiftLint 错误。