简体   繁体   English

防止 Obj-C 代码将“nil”传递给带有非可选参数的 Swift 方法

[英]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

Follow up跟进

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 分析器无法识别此问题。

Objc - Swift 崩溃

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.

相关问题 如何使用 obj-c class 实例删除 swift 非可选解包? - How do I remove swift non-optional unwrapping with obj-c class instance? 如何使用Obj-C中的参数调用Swift方法 - How to invoke a Swift method with parameters from Obj-C Obj-C框架返回nil,并且崩溃我的Swift代码说'致命错误:在展开Optional值时意外发现nil' - Obj-C frameworks returns nil, And crashes my Swift Code saying 'fatal error: unexpectedly found nil while unwrapping an Optional value' 错误桥接 Obj-C 代码和 Swift:方法“Z”提供的方法“U”与协议“Y”中的可选要求方法“X”冲突 - Error bridging Obj-C code and Swift: method "U" provided by method "Z" conflicts with optional requirement method "X" in protocol "Y" 在Swift中检查非可选值是否为nil的最佳方法 - Best way to check non-optional values for nil in Swift 无法在Swift类中调用抛出并从Obj-C返回非void的方法 - Unable to call method in Swift class that throws and has non-void return from Obj-C Obj-C:从导航控制器中的detailViewController返回参数 - Obj-C : Passing parameters back from a detailViewController in a navigation controller 将字典对象从Obj-C传递到Swift - Passing a Dictionary object from Obj-C to Swift 从Swift调用一个名为`init`的Obj-C类方法 - Invoking an Obj-C class method named `init` from Swift 在Swift中移植obj-c委托方法 - Porting obj-c delegate method in Swift
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM