Swift 與 Objc Exception

一、背景

  Swift具備完善的Error handle機制,對於純Swift下面的Error,在編碼的時候能夠正確處理。

  在使用try? 處理拋出Error的方法的時候,會忽略Error,直接返回nil

 

二、Swift 與 Objc下面的Exception

  下面的代碼是經常遇到的一種場景,Swift序列化

    private func serialize(message: Message, pretty: Bool) -> String? {
        var result: String?
        do {
            let data = try JSONSerialization.data(withJSONObject: message, options: pretty ? .prettyPrinted : JSONSerialization.WritingOptions(rawValue: 0))
            result = String(data: data, encoding: .utf8)
        } catch let error {
            log(error)
        }
        return result
    }

  雖然這個序列化的API有標註throws標記,但是拋出的異常是objc的異常,這個swift中的try catch是catch不住的

    /* Generate JSON data from a Foundation object.
  If the object will not produce valid JSON then an exception will be thrown.
  Setting the NSJSONWritingPrettyPrinted option will generate JSON with whitespace designed to make the output more readable.
  If that option is not set, the most compact possible JSON will be generated.
  If an error occurs, the error parameter will be set and the return value will be nil.

  The resulting data is a encoded in UTF-8. */ open class func data(withJSONObject obj: Any, options opt: JSONSerialization.WritingOptions = []) throws -> Data

  如果傳遞一個非可序列化的對象,那麼將會導致下面的Crash

 

  三、規避方案

  Swift部分的方法存在throws的時候,需要特別注意是不是拋出的objc異常,如果是,那麼需要特別處理,針對本例子當中,可以採用下面的方法判斷一個對象是否可以序列化

 

    /* Returns YES if the given object can be converted to JSON data, NO otherwise. The object must have the following properties:
        - Top level object is an NSArray or NSDictionary
        - All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
        - All dictionary keys are NSStrings
        - NSNumbers are not NaN or infinity
     Other rules may apply. Calling this method or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data.
     */
    open class func isValidJSONObject(_ obj: Any) -> Bool

  修改之後的代碼

        guard JSONSerialization.isValidJSONObject(message) else {
            log("\(message) json object not valid")
            return nil
        }

  除此之外,stackoverflow上面還提供一種方案,OC下面封裝一個方法,這個方法內部catch所有NSException的異常信息,然後作爲結果返回出來

  比如:https://stackoverflow.com/questions/32758811/catching-nsexception-in-swift

NSError *tryCatch(void(^tryBlock)(), NSError *(^convertNSException)(NSException *))
{
    NSError *error = nil;
    @try {
        tryBlock();
    }
    @catch (NSException *exception) {
        error = convertNSException(exception);
    }
    @finally {
        return error;
    }
}

  

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章