美文网首页Swift日更
[iOS] Swift调用SDWebImage找不到方法没有自动

[iOS] Swift调用SDWebImage找不到方法没有自动

作者: BudSwift | 来源:发表于2019-05-24 01:44 被阅读0次

    测试环境: Xcode 10.1 Swift 4.2

    如果在 OC 和 Swift 混编的项目中使用了 SDWebImage,那么在 Swift 文件中 imageView 设置网络图片时没有像 OC 中那么自然和顺利,先看 OC:

    // OC
    [imageView sd_setImageWithURL:someURL placeholderImage:somePlaceholder];
    

    自动完成很自然顺畅:


    OC 调用 SDWebImage 的自动完成情况

    然而,Swift 就没有那么好可以自动完成了,同样的尝试:

    Swift 调用 SDWebImage 的自动完成情况
    通过查找方法的源头,从 SDWebImage 的 UIImageView + WebCache.h 的源代码中可以看到一个关键词 NS_REFINED_FOR_SWIFT,如下:
    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
    

    这个方法声明后面紧跟的是 NS_REFINED_FOR_SWIFT 系统的宏定义:

    // Foundation/NSObjcRuntime.h
    #define NS_REFINED_FOR_SWIFT CF_REFINED_FOR_SWIFT
    

    单词 refine 的含义是提炼,顾名思义是只这个函数是从其他函数中提炼而来,由此可以发现 UIImageView+WebCache 中的其他函数也有同样的定义:

    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder
                       options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder
                     completed:(nullable SDExternalCompletionBlock)completedBlock NS_REFINED_FOR_SWIFT;
    

    进入 .m 查看它们的实现,就不难得出结论:这些方法都是由一个更多参数的 sd_setImageWithURL:placeholderImage:options:progress:completed: 提炼而来,其本质是在内部提供了这个多参数函数一些默认参数。

    @implementation UIImageView (WebCache)
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url {
        [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
    }
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
        [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
    }
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
        [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
    }
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
        [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
    }
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
        [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
    }
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
        [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
    }
    
    ....
    @end
    

    那么回到 Swift 的调用,由于 Swift 函数支持默认参数的特性,标记有 NS_REFINED_FOR_SWIFT 的 OC 方法到了 Swift 中就由对应的带有默参数的多参数函数来实现了。因此 Swift 实际调用时先调用多参数函数:

    extension UIImageView {
        func sd_setImageWithURL(_ URL?, 
                placeholderImage: UIImage? = nil, 
                options: [SDWebImageOptions] = [], 
                completed: SDExternalCompletionBlock? = nil)
                { ... }
    }
    

    直接调用此函数,方式一:

    func test() {
        let imageView = UIImageView()
        let url = URL(string: "https://qq.com")
        let placeholder = UIImage(named: "image")
        imageView.sd_setImage(with: url,
                           placeholderImage: placeholder,
                            options: [], 
                            completed: nil)
    }
    

    再结合默认参数特性,将不需要的默认参数直接删除即可,方式二:

    
    func test() {
        let imageView = UIImageView()
        let url = URL(string: "https://qq.com")
        let placeholder = UIImage(named: "image")
        imageView.sd_setImage(with: url, placeholderImage: placeholder)
    }
    
    

    更多的混编使用的宏

    NS_SWIFT_NAME: 用来给一个 OC 函数、类型等一个 Swift 名字

    #define NS_SWIFT_NAME(_name) CF_SWIFT_NAME(_name)
    
    

    反之 Swift 的类型可以在 OC 调用时重命名,使用 @objc(renamed) 语法

    @objc(MBPlacemark)
    open class Placemark: NSObject, Codable {
    ....
    }
    

    加个微信,随时联系 😆

    相关文章

      网友评论

        本文标题:[iOS] Swift调用SDWebImage找不到方法没有自动

        本文链接:https://www.haomeiwen.com/subject/xrqwzqtx.html