swift 4.2 无法将类型“(_)-> Void”的值转换为预期的参数类型“(()-> Void)?”

Posted

技术标签:

【中文标题】swift 4.2 无法将类型“(_)-> Void”的值转换为预期的参数类型“(()-> Void)?”【英文标题】:swift 4.2 Cannot convert value of type '(_) -> Void' to expected argument type '(() -> Void)?' 【发布时间】:2019-01-29 11:35:10 【问题描述】:

==> swift 3 版本完美运行,但 swift 4 和 swift 4.2 正在运行。

static func animate(_ duration: TimeInterval,
                    animations: (() -> Void)!,
                    delay: TimeInterval = 0,
                    options: UIViewAnimationOptions = [],
                    withComplection completion: (() -> Void)! = ) 

    UIView.animate(
        withDuration: duration,
        delay: delay,
        options: options,
        animations: 
            animations()
        , completion:  finished in
            completion()
    )


static func animateWithRepeatition(_ duration: TimeInterval,
                                   animations: (() -> Void)!,
                                   delay: TimeInterval = 0,
                                   options: UIViewAnimationOptions = [],
                                   withComplection completion: (() -> Void)! = ) 

    var optionsWithRepeatition = options
    optionsWithRepeatition.insert([.autoreverse, .repeat])

    self.animate(
        duration,
        animations: 
            animations()
        ,
        delay:  delay,
        options: optionsWithRepeatition,
        withComplection:  finished in
            completion()
    )

xcode 上的错误显示 =>

无法将 '(_) -> Void' 类型的值转换为预期的参数类型 '(() -> 无效)?'

【问题讨论】:

哪一行?删除该行中的`finished in`,因为withComplection没有参数,所以没有“finished”。 离题,但有人可以解释一下!表示在参数声明中animations: (() -> Void)! @JoakimDanielson 查找隐式展开的选项 @DávidPásztor 谢谢,我理解了这个概念,例如在将它用于@IBOutlet 时,但我真的不明白在参数声明中包含它们意味着什么。 @JoakimDanielson 隐式解包选项 (IUO) 始终具有相同的含义。它们是可选值,但是每当访问它们时,它们将被强制解包以提供非可选值(实际上这在 Swift 4.2 中有所改变,现在它们仅在需要非可选值时才被强制解包,否则它们没有打开)。如果将函数输入参数声明为 IUO,则无论何时使用它都会在函数内部强制解包,但您仍然可以传入一个可选参数。这是否有一个真正的用例是一个不同的问题(我会说不)。 【参考方案1】:

您声明了animate 函数,使其completion 参数不接受输入参数。但是,当您在 animateWithRepetition 中调用该函数时,您正尝试在闭包中调用输入参数 finished。只需删除finished,您的代码就可以正常编译。

static func animateWithRepetition(_ duration: TimeInterval, animations: (() -> Void)!, delay: TimeInterval = 0, options: UIView.AnimationOptions = [], withComplection completion: (() -> Void)! = ) 

    var optionsWithRepetition = options
    optionsWithRepeatition.insert([.autoreverse, .repeat])

    self.animate(duration, animations: 
        animations()
    , delay: delay, options: optionsWithRepeatition, withCompletion: 
        completion()
    )

P.S.:我已经更正了您输入参数名称中的拼写错误。传入隐式展开类型的输入参数也没有多大意义。要么将 animations 设为普通的 Optional 并安全地打开它,要么将其设为非 Optional,如果它不应该是 nil

【讨论】:

我要删除 finished 这里显示错误无法将类型 '() -> Void' 的值转换为预期的参数类型 '((Bool) -> Void)?' @Digvijay 在UIView 的扩展中声明你的两个函数时,这段代码对我来说编译得很好。你在哪里定义的? github.com/IvanVorobei/SegmentedControl 我在我的项目中使用了这个库,我正在获取这个问题。 @DávidPásztor 兄弟,我正在使用这个 lib 类,而那个类显示这个错误。 @Digvijay 所以你问题中的两个函数没有在你的代码中声明,而是在链接库中声明?如果是这种情况,您应该为该库打开一个 GitHub 问题并让他们修复他们的代码。如果在您的代码中声明了这些函数,那么您需要使用声明它们的位置更新您的问题。正如我所说,将它们声明为 UIView 的扩展就可以了【参考方案2】:

在你的函数声明中:

static func animate(_ duration: TimeInterval,
                    animations: (() -> Void)!,
                    delay: TimeInterval = 0,
                    options: UIViewAnimationOptions = [],
                    withComplection completion: (() -> Void)! = )

您已将完成处理程序定义为(() -> Void)!,即它没有任何参数。

但是当你调用这个函数时:

self.animate(
        duration,
        animations: 
            animations()
        ,
        delay:  delay,
        options: optionsWithRepeatition,
        withComplection:  finished in
            completion()
    )

您在完成块中提供参数finished。这就是它给出错误的原因。

【讨论】:

以上是关于swift 4.2 无法将类型“(_)-> Void”的值转换为预期的参数类型“(()-> Void)?”的主要内容,如果未能解决你的问题,请参考以下文章

搜索栏在 swift 3 中不起作用。无法将类型 (_) -> Bool 的值转换为预期的参数类型 NSPredicate

使用 PromiseKit 6 在 Swift 4.2 中缓存

错误:无法将类型“(_)->()”的值转换为预期的参数类型“(()-> Void)?”

无法将类型“(_) -> ()”的值转换为预期的参数类型“(() -> Void)?”

Swift 编译器错误:“无法使用 '((_) -> _)' 类型的参数列表调用 'map'”

无法将类型 '(Any) -> ()' 的值转换为预期的参数类型 '(_) -> _'