[英]Prevent Obj-C code from passing `nil` to a Swift method with non-optional parameters
I'm dealing with an issue where Obj-C code can pass nil
to Swift methods that do not take Optional parameters.我正在处理一个问题,其中 Obj-C 代码可以将
nil
传递给不采用可选参数的 Swift 方法。
I'm looking for a way for Xcode compiler to prevent this.我正在为 Xcode 编译器寻找一种方法来防止这种情况发生。 It seems that all nullability annotations are for Swift to call Objc, not vice-versa.
似乎所有的可空性注释都是为了 Swift 调用 Objc,反之亦然。
Some example code:一些示例代码:
// file1.swift
@objc
class Foo: NSObject {
@objc let date: Date? // default to nil
...
}
// file2.swift
extension Date {
@objc(doSomethingWithOtherDate:)
func doSomething(with otherDate: Date) {
print(date)
}
}
Then in Obj-c, we call the Swift method passing in an optional value, with nil
:然后在 Obj-c 中,我们调用 Swift 方法传入一个可选值,其中
nil
:
// file3.m
[Date.new doSomethingWithOtherDate:[Foo.new date]];
Is there a way to prevent this?有没有办法防止这种情况? How can we tell the compiler
doSomethingWithOtherDate
does not take nil
.我们如何告诉编译器
doSomethingWithOtherDate
不采用nil
。
Following up on this issue, passing a literal nil
on the call triggers a warning, which is very helpful.跟进此问题,在调用中传递文字
nil
会触发警告,这非常有帮助。 However, passing a nil
value does not trigger anything.但是,传递一个
nil
值不会触发任何事情。 The static analyzer does however find the issue if the nil reference is local.但是,如果 nil 引用是本地的,static 分析器确实会发现问题。
However, if a nil
reference is passed via another object, the static analyzer fails to identify this issue.但是,如果通过另一个 object 传递
nil
引用,则 static 分析器无法识别此问题。
I've made this repo to showcase this issue: https://github.com/eneko/ObjcCrashDemo我做了这个 repo 来展示这个问题: https://github.com/eneko/ObjcCrashDemo
In general, no.一般来说,没有。 Objective-C does not have enough understanding of nullability to detect every case.
Objective-C 对可空性的了解不足,无法检测到所有情况。
If you explicitly pass nil you should get a warning "Null passed to a callee that requires a non-null argument".如果你显式地传递 nil 你应该得到一个警告“Null passed to a callee that requires a non-null argument”。 You can turn this into an error by adding
-Werror=nonnull
to "Other Warning Flags" in your build settings.您可以通过将
-Werror=nonnull
添加到构建设置中的“其他警告标志”来将其转化为错误。
However this is extremely limited.然而,这是极其有限的。 Even something as simple as
NSDate* date = nil;
甚至像
NSDate* date = nil;
这样简单的东西and passing that will produce no warning/error.并通过它不会产生警告/错误。 Even adding a
nonnull
property in Objective-C and passing that will not produce a warning/error.即使在
nonnull
中添加一个非空属性并传递它也不会产生警告/错误。
I was able to find this article: https://fabiancanas.com/blog/2020/1/9/swift-undefined-behavior.html (search for the "Detecting nil when nil isn't possible" section).我能够找到这篇文章: https://fabiancanas.com/blog/2020/1/9/swift-undefined-behavior.html (搜索“当 nil 不可能时检测 nil”部分)。 This article discusses a rather complex solution to the problem, but I would suggest the easier solution would be to declare your function argument type as
Date!
本文讨论了一个相当复杂的问题解决方案,但我建议更简单的解决方案是将 function 参数类型声明为
Date!
(either a value or nil) and then perform a guard let
on the passed value before proceeding in the function body: (一个值或 nil)然后在继续处理 function 主体之前对传递的值执行
guard let
:
// file2.swift
extension Date {
@objc(doSomethingWithOtherDate:)
func doSomething(with otherDate: Date!) {
guard let od = otherDate else {
// do something else
return
}
print(date)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.