ios - 检查 Swift 中未初始化的非可选值?
问题描述
我有一些代码已经运行了很长时间,但突然导致崩溃 ar 运行时。这可能是因为这是它第一次获得 nil 值(由于某些故障或其他原因),但无论如何我的应用程序现在在启动时崩溃了。
代码是:
@objc func download(surl: NSString, completion : @escaping (NSData) -> Void ) {
print("surl to download is:",surl)//CRASHES HERE if surl is uninitialized.
它在错误指示的行上崩溃:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
这是调试器中的一行,它说它在崩溃时是“unitiailized”的。
我不愿意将 surl 更改为可选的,因为此方法在应用程序中被称为无数地方,我担心在方法中更改它会导致其他问题。
所以想找出一种方法来测试 surl 是否未初始化并在可能的情况下返回。
感谢您的任何建议。
编辑:
我在调用上述方法并通过了not nil测试的方法中尝试了not nil的测试。但是如果你尝试用它做点什么,它就会崩溃。此外,崩溃后在控制台中打印它会给出:(NSString) $R2 = <uninitialized>
这是屏幕截图:
解决方案
可能是您的 Swift 代码是从 Objective-C 调用的,而 Objective-C 将 nil 发送给 Swift。这可以解释为什么你会在链的末端发生崩溃,只有在实际使用该值的地方。
注意,Objective-C 很乐意将一个 nil 值传递给一个不接受 nil 的 Swift 函数,而且 Swift 也会很高兴地将1那个 nil 值转发到只允许非 nil 的地方,只在它实际尝试使用的地方崩溃价值。
从我在您的堆栈跟踪中看到的内容来看,这似乎是问题所在:Objective-C-[IDModel updateCa..]
方法调用Utilities.downloadImag...
Swift 方法,该方法将调用转发到Utilities.download(surl..
,当尝试使用值时,崩溃发生在链中的最后一个函数要使用的。
为了将更改的影响降到最低,您可以做的是“重载”该函数,一个surl
用于 Objective-C 世界的可选函数,一个用于 Swift 世界的函数:
@objc(download) func objcDownload(surl: NSString?, completion : @escaping (NSData) -> Void ) {
guard let surl = surl else {
// handle this problems
return
}
// forward to the worker function
download(surl: surl, completion: completion)
}
// @nonobjc might not be needed, depending of the class declaration
// but being explicit doesn't hurt
@nonobjc func download(surl: NSString, completion : @escaping (NSData) -> Void ) {
// same code, no changes needed
}
这边走:
- Objective-C 代码将看到相同的功能,无需更改
- Objective-C 桥的 Swift 实现可以检查 nil
- Swift 代码仍然可以使用 now
@nonobjc
download 功能。
如果你对从 Objective-C 传递给 Swift 的 nil 值不信任我,这里有一个例子来证明这一点:
// in a header file, imported in the bridging header
@interface ObjCWorker: NSObject
+ (void)sendNilToSwift;
@end
// in the corresponding .m file
@implementation ObjCWorker
+ (void)sendNilToSwift {
NSString *shouldNotBeNil = nil;
[SwiftWorker doWorkWithNonNull:shouldNotBeNil];
}
@end
// in a Swift file
class SwiftWorker: NSObject {
@objc static func doWork(with string: NSString) {
delegateWorkToSomeOtherMethod(string)
}
static func delegateWorkToSomeOtherMethod(_ string: NSString) {
delegateWorkToAnotherMethod(string)
}
static func delegateWorkToAnotherMethod(_ string: NSString) {
print(string)
}
}
现在,只需编写ObjCWorker.sendNilToSwift()
,您就会遇到完全相同的崩溃。
1请注意,这目前仅适用于 Objective-C 参数:NSString、NSData、...、桥接的 Swift 类型(如 String、Data)在从 Objective-C 端作为 nil 值发送时以某种方式被初始化为空值。
推荐阅读
- javascript - Tampermonkey 用户脚本通过关键字搜索获取表格单元格数据?
- api - 如何在 Rest Assured Framework 中使用 POST 方法
- java - 数据绑定 Swing Eclipse beansbinding-1.2.1.jar WindowBuilderPro
- scala - 为什么命令行出现“不是包的成员”和“找不到类”错误,而不是 Intellij?
- python - Pandas - 获取分组数据的最新“n”列值
- java - IllegalStateException:在 getTitle() 时无法使用 HtmlUnitDriver 按名称定位 com.gargoylesoftware.htmlunit.UnexpectedPage 的元素
- ruby - Carrierwave 是线程安全的吗?
- pyspark - 如何将 PySpark 数据框写入 DynamoDB 表?
- ios - 在上传到应用商店之前创建我的应用的应用商店链接
- javascript - 无法使用 Jquery 替换文本