Alamofire源码之URLConvertible

Alamofire中进行网络请求的方法如下

func request(
    _ url: URLConvertible,
    method: HTTPMethod = .get,
    parameters: Parameters? = nil,
    encoding: ParameterEncoding = URLEncoding.default,
    headers: HTTPHeaders? = nil)
    -> DataRequest

其中,请求的url并非我们熟悉的URL或者String,而是一个URLConvertible类型。URLConvertible是一个协议,只有一个方法需要实现

func asURL() throws -> URL

这个方法返回可抛出错误的URl对象,间接为网络请求提供url。Alamofire中默认有String,URL,URLComponents遵守并实现此协议,可以很方便的供请求网络使用

我们可以放弃一下两种代码
1.直接使用string类型,并且在每次请求的时候转化成URL,使用这种方式,会在整个app中出现大量重复的代码

guard let url = URL(string: "") else { return }
xxxxxxxxxx

2.又或者直接的为String/URLComponents写个extension,返回对应的URL

extension String {
  func asurl() -> URL? {}
}

extension  URLComponents {
  func asurl() -> URL? {}
}

这种方式虽然比第一种舒服一些,但是仍然不够简洁----因为它们之间没有共性,不够范型,我们很有可能写出两个基本相同的方法,变的只有参数类型

func request(url: String) {
  guard let url = url.asurl() else { return }
xxxx
}

func request(url: URLComponents) {
  guard let url = url.asurl() else { return }
xxxx
}

--------------------------------我是分割线--------------------------
下面来讲一个比较实用的栗子:
在swift中,我们一般使用Kingfisher来图片的请求,而Kingfisher中也是用了一个Resource协议来对ImageView进行请求extension

func setImage(with resource: Resource?,
                         placeholder: Placeholder? = nil,
                         options: KingfisherOptionsInfo? = nil,
                         progressBlock: DownloadProgressBlock? = nil,
                         completionHandler: CompletionHandler? = nil) -> RetrieveImageTask

这个是Resource协议,只需要提供两个变量就行

public protocol Resource {
    var cacheKey: String { get }
    var downloadURL: URL { get }
}

而Kingfisher只默认提供了URL的Resource协议,所以我们可以用URL对象来请求图片。

假如我们有一个Book结构体

struct Book {
    let name: String
    let pic: String
}

如果需要展示book的书籍的封面,我们可以这样使用

 func setPic(from book: Book) {
        let imgv = UIImageView()
        imgv.kf.setImage(with: URL(string: book.pic))
    }

注意魔法来了,假如Book也遵守并实现了Resource协议,我们可以把代码写的更简洁

extension Book: Resource {
    var downloadURL: URL {
        return URL(string: pic)!
    }
    
    var cacheKey: String {
        return name
    }
}

然后我们可以这样写,是不是很方便。

 func setPic(from book: Book) {
        let imgv = UIImageView()
        imgv.kf.setImage(with: book)
    }

可能Book结构体太过简单,觉得两种方法都可以,没什么大的区别。我们想一下以下场景:
封面url并不是Book的一级属性,而是它内部嵌套的其它对象中的数组/字典中取到的,我们在使用的时候是不是可以省去很多解析

你可能感兴趣的:(Alamofire源码之URLConvertible)