![](/img/trans.png)
[英]Prevent Obj-C code from passing `nil` to a Swift method with non-optional parameters
[英]Best way to check non-optional values for nil in Swift
在Swift中,这种情况很少见,但最终可能会得到一个非零类型的值,该值具有nil值。 如对这个问题的回答所述 ,这可能是由桥接到Swift的不良Objective-C代码引起的:
- (NSObject * _Nonnull)someObject {
return nil;
}
或通过错误的Swift代码:
class C {}
let x: C? = nil
let y: C = unsafeBitCast(x, to: C.self)
在实践中,我已经使用MessageUI
的MFMailComposeViewController
API进行了此操作。 以下代码创建了一个非可选的MFMailComposeViewController
,但是,如果用户尚未在Mail中设置电子邮件帐户,则以下代码将因EXC_BAD_ACCESS
崩溃:
let mailComposeViewController = MFMailComposeViewController()
print("\(mailComposeViewController)")
调试器如下所示显示mailComposeViewController
的值:
mailComposeViewController = (MFMailComposeViewController) 0x0000000000000000
我在这里有几个问题:
unsafeBitCast(_:to:)
的文档说它“破坏了Swift类型系统的保证”,但是Swift文档中有一个地方可以解释这些保证可以被打破,以及如何/何时? mailComposeViewController == nil
因为它不是可选的。 甚至Apple的API有时也会针对API中未标记为Optional的类型返回nil
。 解决方案是将其分配给Optional。
例如,有一段时间traitCollectionDidChange
返回了一个UITraitCollection,即使它实际上可能是nil
。 您无法将其检查为nil
因为Swift不会让您检查nil
的non-Optional。
解决方法是立即将返回值分配给UITraitCollection?
并检查了nil
。 无论您的用例是什么,这种事情都应该起作用(尽管您的邮件示例不是用例,因为您一开始就做错了)。
我有同样的问题,但我使用了苹果文档中的建议。
从文档中:
在呈现邮件撰写视图控制器之前,请始终调用canSendMail()方法以查看当前设备是否配置为发送电子邮件。 如果未将用户的设备设置为可以发送电子邮件,则可以通知用户或仅在应用程序中禁用电子邮件发送功能。 如果canSendMail()方法返回false,则不应尝试使用此接口。
if !MFMailComposeViewController.canSendMail() {
print("Mail services are not available")
return
}
考虑使用unsafeBitCast(_:to:)
。
主要问题在于,在此方法中,如果该指针可以符合我们期望的类型,则无需任何验证就可以将指针从Swift转换为值,从我的角度来看,这很危险,因为它会导致崩溃。
使用实际的Swift指针类型可能有更好的方法,但是一种选择可能是仅查看地址:
func isNull(_ obj: AnyObject) -> Bool {
let address = unsafeBitCast(obj, to: Int.self)
return address == 0x0
}
( Int
被记录为机器字大小。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.