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; } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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