链式调用的实现思路(Swift)

1,222 阅读4分钟

链式调用:返回对象然后调用对应对象的方法即可实现

一个例子

例子一

Piggy.m

-(Piggy *)buy_wood{
    NSLog(@"买木材");
    return self;//这里的思路很关键
}
-(Piggy *)build_A_House{
    NSLog(@"盖房子");
    return self;//这里的思路很关键
}

实现

Piggy * pig = [[[Piggy new] buy_wood] build_A_House];

输出
盖房子
买木材

在我们使用时难免有些麻烦,而且也不雅观,对吧。当然还有更好的方法

例子二

Piggy.m

- (Piggy *(^)(void))buy_wood{
    NSLog(@"买木材");
    return ^{
        
        return self;
    };
    
}

- (Piggy *(^)(void))build_A_House{
    NSLog(@"盖房子");
    return ^{
        return self;
    };
}

实现

Piggy *pig = [Piggy new];
pig.buy_wood().build_A_House();

输出
盖房子
买木材

怎么样,有内味了吧,如果再加上参数呢

例子三

- (Piggy *(^)(NSString *))buy_wood{
    
    return ^(NSString *content){
        NSLog(@"在%@买木材", content);
        return self;
    };
}

- (Piggy *(^)(NSString *))build_A_House{
    
    return ^(NSString * content){
        NSLog(@"在%@盖房子", content);
        return self;
    };
}

实现

pig.buy_wood(@"上海").build_A_House(@"北海");
输出
在上海买木材
在北海盖房子

由此我们可以看出,小猪真是小笨猪🐷 。当然,我们依然可以观察到,运用链式调用的方法,在一定程度上简化了我们实现过程中一些繁琐的写法,并且在它的方法在它的对象身边更集中了,使用点语法一定程度上拉近了我们操作对象的距离,在维护的时候也更容易在一段代码中找到关键信息

由于Swift天然的语法优势,在对闭包的使用上相较于OC代码,使用链式编程的贴合度更高,并且更加方便易使用,所以,如果你会Swift语法,那么学习链式编程就是一个很好的开始!

学以致用

1.自定义弹出视图

//弹窗封装

import UIKit

enum OtherMsgItemMode {
    case left
    case right
}

class OtherMsgView: UIView, PopupProtocol, XIBProtocol {
    @IBOutlet weak var msgLab: UILabel!
    @IBOutlet weak var leftBtn: UIButton!
    @IBOutlet weak var rightBtn: UIButton!
    
    typealias ItemHandlerType = ((OtherMsgItemMode) -> Void)
    
    private var leftTitle: String?//
    private var rightTitle: String?//
    private var description: String?//
    private var action: ItemHandlerType?//
    
    override func layoutSubviews() {
        super.layoutSubviews()
        self.layer.cornerRadius = 12
        self.backgroundColor = .white
        
        leftBtn.setTitle(leftTitle, for: .normal)
        rightBtn.setTitle(rightTitle, for: .normal)
        msgLab.text = description
        
        leftBtn.addTarget(self, action: #selector(leftTarget))
        rightBtn.addTarget(self, action: #selector(rightTarget))
        
    }
    @IBAction func click(_ sender: UIButton) {
        PopupController.dismiss(self)
    }
    
    @objc func leftTarget() {
        PopupController.dismiss(self)
        action?(.left)
    }
    
    @objc func rightTarget() {
        PopupController.dismiss(self)
        action?(.right)
    }
    
}


extension Aiolia_Soul_OtherMsgView {
    func open(_ viewController: UIViewController?) -> Void {
        PopupController.show(self, presentingViewController: viewController)
        return
    }
    
    func action(_ handler: @escaping ItemHandlerType) -> Self {
        self.action = handler
        return self
    }
    
    func itemTitle(left: String, right: String) -> Self {
        self.leftTitle = left
        self.rightTitle = right
        return self
    }
    
    func description(_ text: String) -> Self {
        self.description = text
        return self
    }
}

实现

OtherMsgView.loadFromNib()?
    .itemTitle(left: "取消", right: "确认")
    .content("确认删除账号吗?")
    .action({ (item) in
    })
    .open(vc)

2.网络层封装

//  网络层封装

import Foundation
import Alamofire

enum HttpRequestType {
    case get
    case post
    
}

extension HttpRequestType: CustomStringConvertible {
    var description: String {
        switch self {
        case .get: return "GET"
        case .post: return "POST"
        }
    }
}


//Networkkit属性设置
class NetworkKit {
    
    typealias SuccessHandlerType = ((Data) -> Void)
    typealias FailureHandlerType = ((Int, String) ->Void)
    typealias FinishHandlerType = ((Any?) -> Void)
    typealias TimeOutHandlerType = ((String) -> Void)
    
    private var requestType: HttpRequestType = .post//请求类型
    private var url: String?//URL
    private var headers: [String: String] = ["Accept":"application/json", "Content-Type":"application/json"]//header
    private var params: [String: Any]?//参数
    private var timeoutInterval: TimeInterval = 15  // 超时时间
    private var success: SuccessHandlerType?        // 成功的回调
    private var failure: FailureHandlerType?        // 失败的回调
    private var finish: FinishHandlerType?          // 完成的回调
    private var timeOut: TimeOutHandlerType?        // 超时的回调
    private var httpRequest: Request?
    
}

//NetworkKit属性的设置
extension NetworkKit {
    ///设置url
    func url(_ url: String?) -> Self {
        self.url = url
        return self
    }
    
    ///设置post/get 默认post
    func requestType(_ type:HttpRequestType) -> Self {
        self.requestType = type
        return self
    }
    
    ///设置请求头
    func headers(_ headers: [String: String]) -> Self {
        self.headers = headers
        return self
    }
    
    ///设置参数
    func params(_ params: [String: Any]?) -> Self {
        self.params = params
        return self
    }
    
    ///设置超时
    func timeoutInterval(_ timeoutInterval: TimeInterval) -> Self {
        self.timeoutInterval = timeoutInterval
        return self
    }
    
    
    ///成功的回调
    func success(_ handler: @escaping SuccessHandlerType) -> Self {
        self.success = handler
        return self
    }
    
    ///失败的回调
    func failure(handler: @escaping FailureHandlerType) -> Self {
        self.failure = handler
        return self
    }
    
    ///完成的回调
    func finish(handler: @escaping FinishHandlerType) -> Self {
        self.finish = handler
        return self
    }
    
    ///超时的回调
    func timeOut(handler: @escaping TimeOutHandlerType) -> Self {
        self.timeOut = handler
        return self
    }
    
    
}



//NetworkKit请求相关
extension NetworkKit {
    
    ///发起请求 设置好相关参数后再调用
    func httpRequest() -> Void {
        var dataRequest: DataRequest?//alamofire请求后的返回值
        
        //发起请求
        if let URLString = url {
            ProgressHUD.show()
            let method = requestType == .get ? HTTPMethod.get : HTTPMethod.post
            let encoding: ParameterEncoding = requestType == .get ? URLEncoding.default : JSONEncoding.default
            guard let params = params else {
                return
            }
            // Alamofire原始方法, 不能设置timeoutInterval超时时间
            //dataRequest =  Alamofire.request(URLString, method: method, parameters: params as Parameters, encoding: encoding, headers: headers)
                        
            
            var myRequest = URLRequest(url: URL(string: URLString)! as URL)
            myRequest.httpMethod = method.rawValue
            myRequest.httpBody = params.toJSONString()?.data(using: .utf8)
            myRequest.timeoutInterval = timeoutInterval
            myRequest.allHTTPHeaderFields = headers
            
            dataRequest =  Alamofire.request(myRequest)
            
            httpRequest = dataRequest
        }
        
        dataRequest?.responseJSON(options: [.mutableLeaves, .allowFragments, .mutableContainers], completionHandler: { (response) in
            ProgressHUD.hide()
            
            
            guard response.error == nil else {
                if response.error!._code == NSURLErrorTimedOut {
                    //handle timeout here
                    print("Code=-1001 The request timed out.")
                    
                    self.timeOut?(response.error!.localizedDescription)
                }else {
                    self.failure?(response.error!._code, response.error!.localizedDescription)
                }
                return
            }
            
            let data = response.data.map { String(decoding: $0, as: UTF8.self) }
            
            guard let jsonData = data else {
                return
            }
            
            self.finish?(jsonData.toDictionary())
            
        })
        
    }
    
    ///取消请求
    func httpCancel() {
        httpRequest?.cancel()
    }
    
}

实现

NetworkKit()
    .timeoutInterval(timeoutInterval)
    .url("\(baseURL)xx")
    .params(params)
    .requestType(.post)
    .timeOut { (msg) in
    }
    .failure(handler: { (errorCode, errorMsg) in
    })
    .finish { (result) in
    }.httpRequest()

以上就是链式调用的全部内容,并没有很复杂的说明,往往在我们写的过程中只需要注意三个条件:链式对象,链式方法调用,以及传值和对结果的后续处理,如果实在没有理解也没关系,只需记住链式调用始终返回self自身。