美文网首页
swift 闭包(block) 与泛型T结合使用,正确写法

swift 闭包(block) 与泛型T结合使用,正确写法

作者: 大鼓书 | 来源:发表于2021-03-29 01:57 被阅读0次

一开始我在闭包里使用了泛型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
  1. 定义swift方法的时候,如果带上<T>, 那么在该方法参数或返回值里必须也要有T,要不然编译不通过,参考上面代码的 “单例封装类”
  2. 一般的block写法,resultP : BaseResponse 后面的 : BaseResponse是可以省去的,但是这里不能省,即便是加上(_ 也不能省;因为调用swift方法的时候方法名后面不能加上<T> ,这样的话,编译器只能根据参数或者返回值中对应的那个T 去找到 方法名的<T>,所以不能省 : BaseResponse。参考上面代码的 “外部调用代码”
  3. 既然已经不能省 “: 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

相关文章

网友评论

      本文标题:swift 闭包(block) 与泛型T结合使用,正确写法

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