Swift 与 Objc Exception

一、背景

  Swift具备完善的Error handle机制,对于纯Swift下面的Error,在编码的时候能够正确处理。

  在使用try? 处理抛出Error的方法的时候,会忽略Error,直接返回nil

 

二、Swift 与 Objc下面的Exception

  下面的代码是经常遇到的一种场景,Swift序列化

1
2
3
4
5
6
7
8
9
10
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不住的

1
2
3
/* Generate JSON data from a Foundation object.<br>   If the object will not produce valid JSON then an exception will be thrown. <br>  Setting the NSJSONWritingPrettyPrinted option will generate JSON with whitespace designed to make the output more readable. <br>  If that option is not set, the most compact possible JSON will be generated. <br>  If an error occurs, the error parameter will be set and the return value will be nil. <br><br>  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异常,如果是,那么需要特别处理,针对本例子当中,可以采用下面的方法判断一个对象是否可以序列化

 

1
2
3
4
5
6
7
8
/* 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

  修改之后的代码

1
2
3
4
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

1
2
3
4
5
6
7
8
9
10
11
12
13
NSError *tryCatch(void(^tryBlock)(), NSError *(^convertNSException)(NSException *))
{
    NSError *error = nil;
    @try {
        tryBlock();
    }
    @catch (NSException *exception) {
        error = convertNSException(exception);
    }
    @finally {
        return error;
    }
}

  

  

posted @   兜兜有糖的博客  阅读(120)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2018-07-13 面试题一《swift和oc的区别》
2018-07-13 iOS面试题详解-开篇
2017-07-13 微信iOS消息拦截插件教程-Tweak HelloWorld
点击右上角即可分享
微信分享提示