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的一级属性,而是它内部嵌套的其它对象中的数组/字典中取到的,我们在使用的时候是不是可以省去很多解析