为啥不能快速推断闭包类型

Posted

技术标签:

【中文标题】为啥不能快速推断闭包类型【英文标题】:Why can't swift infer the closure type为什么不能快速推断闭包类型 【发布时间】:2018-12-26 20:23:06 【问题描述】:

使用 Swift 的第一周,在 Xcode 10.1 上使用 Swift 4.2 新创建的项目),我是 following a tutorial on a how to make a photo gallery app 我对编译器错误感到震惊。

我的情况是这样,在自定义 ViewController 中继承自 UIViewController 并导入 UIKitPhotos。这个方法被 viewWillAppear 调用为 self.displayPhoto

self.photosAssetself.index 由 segue 上的前一个 viewController 设置。

func displayPhoto() 
    let imageManager = PHImageManager.default()
    var ID = imageManager.requestImage(
        for: self.photosAsset[self.index] as PHAsset,
        targetSize: PHImageManagerMaximumSize,
        contentMode: .aspectFit,
        options: nil,
        resultHandler:  (result:UIImage!, info:NSDictionary!) in
            self.imgView.image = result
        
    )

Xcode 抱怨 无法在当前上下文中推断闭包类型 用于 resultHandler 中的闭包。有什么类型可以推断?

Looking at the documentation 看起来 resultHandler 有一个 void 返回类型:

【问题讨论】:

只要不通过明确给出错误的类型来搞乱类型推断,就没有类型可以推断。 感谢您的所有帮助,但为什么投反对票? 好吧,你自己链接到文档,答案就在你面前。文档说UIImage?,你说UIImage! 文档说[AnyHashable : Any]?,你说NSDictionary! 我没有投反对票,但我明白为什么有人会投反对票。 【参考方案1】:

resultHandler 中,您应该使用(image, _) 而不是(result:UIImage!, info:NSDictionary!)

func displayPhoto() 
    let imageManager = PHImageManager.default()
    var ID = imageManager.requestImage(
        for: self.photosAsset[self.index] as PHAsset,
        targetSize: PHImageManagerMaximumSize,
        contentMode: .aspectFit,
        options: nil,
        resultHandler:  (image, _) in
            self.imgView.image = image
        
    )

注意:要改进您的方法,您可能需要在options: 中设置PHImageRequestOptions

func displayPhoto() 
    let imageManager = PHImageManager.default()
    let requestOption = PHImageRequestOptions()
    requestOption.isSynchronous = true
    requestOption.deliveryMode = .highQualityFormat

    var ID = imageManager.requestImage(
        for: self.photosAsset[self.index] as PHAsset,
        targetSize: PHImageManagerMaximumSize,
        contentMode: .aspectFit,
        options: requestOption,
        resultHandler:  (image, _) in
            self.imgView.image = image
        
    )

【讨论】:

【参考方案2】:

你可以用Dictonary代替NSDictionary,但是不需要声明handler的参数类型

...  result, info in
    ...

您也不必指定[AnyHashable : Any]? 类型的参数,因为您不需要它,只需在此处添加下划线_

...  image, _ in
    self.imgView.image = image

【讨论】:

【参考方案3】:

你自己打错了闭包。正确的类型是:

@escaping (UIImage?, [AnyHashable : Any]?) -> Void

你有:

(result:UIImage!, info:NSDictionary!) in

这是错误的。这对编译器非常不利!摆脱编译器的阻碍,它推断类型;它比你更清楚它们的优点。写

result, info in

一切都会好起来的。

【讨论】:

以上是关于为啥不能快速推断闭包类型的主要内容,如果未能解决你的问题,请参考以下文章

为啥 TS 中的泛型接口不能正确推断类型?

为啥 Rust 不能推断出 Iterator::sum 的结果类型?

为啥 Crystal 不能在初始化程序中推断出这种类型?

为啥 Go 编译器不能推断结构实现了接口 [关闭]

一个 lambda 的返回类型可以通过返回值来推断,那么为啥不能是一个函数呢?

为啥我不能使用闭包创建 Fetched Results Controller?