一开始我在闭包里使用了泛型T,试了好多方式,总是编译器不通过,网上的解释也很少,最后看了这篇http://ask.sov5.cn/q/P6f5xloFdL 才算终于写对,然后我特意总结了一下细节
先列出正确写法:
先申明一个block
typealias EWResponseSuccess<T: HandyJSON> = (_ resp: T) -> Void //Void也可以修改为()
//(_ resp: T) 也可以修改为 (T),目前没发现有什么区别
//普通的block定义,最后回调时候,(err: AnyObject) in 可以省略为 err in
typealias EWResponseFail = (_ error: AnyObject) -> Void
//单例封装类:
public func get<T: HandyJSON>(path: String,
params: [String: String]?,
success: @escaping EWResponseSuccess<T>,
error: @escaping EWResponseFail) {
//正式调用AF代码请求服务器
AF.request(lastUrl,
method: httpMethod,
parameters: params,
encoder: URLEncodedFormParameterEncoder.default)
.responseString { response in
// response 的全写为 (response :AFDataResponse<String>) 记得一定要带上(),怎么知道response的类型?,点击responseString进去看到的
switch response.result {
case .success:
if let animal:T = T.deserialize(from: response.value) {
success(animal)
} else {
error("json解析失败" as AnyObject)
}
case .failure(let err):
// NSLog("response = failure %@",err)
error(err as AnyObject)
debugPrint(err)
}
}
}
//外部调用代码:
EWNetworking.ShareInstance.get(path: path, params: ["keyword": "小"], success: { (resultP : BaseResponse) in
}, error: { error in
})
//BaseResponse 是 class ,继承: HandyJSON
- 定义swift方法的时候,如果带上<T>, 那么在该方法参数或返回值里必须也要有T,要不然编译不通过,参考上面代码的 “单例封装类”
- 一般的block写法,resultP : BaseResponse 后面的 : BaseResponse是可以省去的,但是这里不能省,即便是加上(_ 也不能省;因为调用swift方法的时候方法名后面不能加上<T> ,这样的话,编译器只能根据参数或者返回值中对应的那个T 去找到 方法名的<T>,所以不能省 : BaseResponse。参考上面代码的 “外部调用代码”
- 既然已经不能省 “: BaseResponse” 了,那么就还要加上() , 不加()也会报错
看一下非逃逸闭包的书写方式
override func viewDidLoad() {
test {
NSLog("非逃逸")
}
NSLog("End")
}
func test(callback2:()->()) {
NSLog("1")
callback2()
NSLog("2")
}
2021-03-31 16:27:09.345164+0800 QSwift[62528:1044728] 1
2021-03-31 16:27:09.345439+0800 QSwift[62528:1044728] 非逃逸
2021-03-31 16:27:09.345597+0800 QSwift[62528:1044728] 2
2021-03-31 16:27:09.345734+0800 QSwift[62528:1044728] End
顺便回顾一下闭包有返回值情况下的写法
override func viewDidLoad() {
// (a: Int) 可以省略为 a
test (url: "user/list", mydic: ["userid": "4766" , "page":"1"]) {(a: Int) in
NSLog("viewDidLoad_sec %d",a)
return String(format: "方式二 %d", a);
}
//上面这个写法,是建立在callback2 是最后一个参数 ,才可以写在小括号外面。正常的写法是下面这样
test (url: "user/list", mydic: ["userid": "4766" , "page":"1"], callback2:{(a: Int) in
return String(format: "方式二 %d", a);
})
NSLog("End")
}
func test(url: String, mydic: [String:String]? ,callback2: (_ a : Int) -> String) {//一定要写_ ,不能省略_ , 否则编译报错
NSLog("1")
let w: Int = 123
let result: String = callback2(w)
NSLog("2 %@",result)
}
2021-03-31 17:04:45.451286+0800 QSwift[64455:1071686] 1
2021-03-31 17:04:45.451720+0800 QSwift[64455:1071686] viewDidLoad_sec 123
2021-03-31 17:04:45.452047+0800 QSwift[64455:1071686] 2 方式二 123
2021-03-31 17:04:45.452193+0800 QSwift[64455:1071686] End
再看下逃逸闭包
override func viewDidLoad() {
test (url: "user/list", mydic: ["userid": "4766" , "page":"1"]) {(a: Int) in
NSLog("viewDidLoad_sec %d ; %@",a,(Thread.current))
return String(format: "方式二 %d", a);
}
NSLog("End")
}
func test(url: String, mydic: [String:String]? ,callback2:@escaping (_ a : Int) -> String) {//一定要写escaping , 否则编译报错
NSLog("test start")
let w: Int = 123
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
NSLog("asyncAfter %@",(Thread.current))
let result: String = callback2(w)
NSLog("2 %@",result)
}
NSLog("test end")
}
2021-03-31 17:45:50.109258+0800 QSwift[66383:1102064] test start
2021-03-31 17:45:50.113689+0800 QSwift[66383:1102064] test end
2021-03-31 17:45:50.113918+0800 QSwift[66383:1102064] End
2021-03-31 17:45:53.112361+0800 QSwift[66383:1102064] asyncAfter <NSThread: 0x6000001a0100>{number = 1, name = main}
2021-03-31 17:45:53.114229+0800 QSwift[66383:1102064] viewDidLoad_sec 123 ; <NSThread: 0x6000001a0100>{number = 1, name = main}
2021-03-31 17:45:53.114861+0800 QSwift[66383:1102064] 2 方式二 123
网友评论