Swift中Result型別的強大功能

AndreaArlex同志發表於2019-04-19

Swift型別系統的一大好處是它可以讓我們在處理各種操作的結果時消除很多歧義。通過泛型和列舉值等功能,我們可以輕鬆建立型別,讓我們利用編譯器來確保我們以正確的方式處理結果。

這種型別的一個例子是Result型別 - 雖然它(尚未)構建到標準庫中,但它是一種在許多不同的Swift專案中很常見的型別。我們將探討這種結果型別,以及它與Swift的一些語言功能結合使用時可以做的一些很酷的事情。

網路請求是我們經常用到的場景,而網路請求一般會有2種結果:

  1. 成功
  2. 失敗 讓我們來看看afnetworking框架是怎麼去處理他們的結果的:
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
[session GET:@"需要請求的url" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"請求成功");
} failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"請求失敗");        
}];
複製程式碼

顯然,他通過2個block來處理成功與失敗的回撥,但是,我們能不能用一個物件去處理完這種事情呢??? ***Result***型別可以幫到你.....????

####讓我們來看看什麼是***Result***型別:

public protocol TDWSuccessedProtocol {
    
}

public protocol TDWFailedProtocol {
    
}

public enum TDWResult<T:TDWSuccessedProtocol, Error:TDWFailedProtocol> {
    case success(T)
    case failure(Error)
    
    public init(value:T) {
        self = .success(value)
    }
    
    public init(error:Error) {
        self = .failure(error)
    }
    
}
複製程式碼

以上就是一個很基礎的***Result***的型別。

1、我們先定義2個協議:

  • TDWSuccessedProtocol 成功的協議,可以擴充套件成功的物件需要的任何東西。
  • TDWFailedProtocol 失敗的協議,可以擴充套件失敗的物件需要的任何東西。

2、我們建立一個TDWResult列舉 列舉有2個泛型,T***繼承***TDWSuccessedProtocolError***繼承***TDWFailedProtocol。列舉有2種情況,一種是成功(success),一種是失敗(failure),還有對應的初始化。 這樣,我們就完成了一個***Result***型別的定義了。

####如何使用呢? 以一個網路請求為例子:

struct TDWSuccess:TDWSuccessedProtocol {
    
}

struct TDWFailure:TDWFailedProtocol {
    
}

typealias Completion = (_ result:TDWResult<TDWSuccess,TDWFailure>)->Void

class TDWNetworkTest {
    
    class func tdw_request(parameters:String,completion:@escaping Completion) {
        
        //network request
        
        if parameters.count > 0 {
            let successResult = TDWSuccess()
            completion(TDWResult(value: successResult))
            
        } else {
            
            let failResult = TDWFailure()
            completion(TDWResult(error: failResult))
            
        }
        
        
    }
    
}
複製程式碼

呼叫:

TDWNetworkTest.tdw_request(parameters: "abc") {(result) in
            
            switch result {
                
            case .success(let response):
                print(response)
                
            case .failure(let response):
                print(response)
            }
            
        }
複製程式碼

這樣做的話,我們要擴充套件就比較簡單了,不用再多定義個block,多定義元組,我們直接在***TDWResult***裡面多定義一種case就可以了,擴充套件性就大大增強了。???

如果覺得小弟說得不對,歡迎指正_________謝謝!!!!

相關文章