【问题标题】:Block with multiple parameters as argument in swift/objective-c在 swift/objective-c 中使用多个参数作为参数的块
【发布时间】:2016-02-23 21:24:18
【问题描述】:

我正在尝试将 Swift 函数(具有多个参数,定义为闭包)传递给 Objective-C 函数。从技术上讲,该函数是在 Objective-C++ 中定义的,但是我在标题级别遇到了一个问题,因此对于这个问题应该是等效的。

在 Objective-C 标头中,我将其定义为:

@interface MyObjCClass : NSObject
typedef void (^MyCallback)(NSMutableData*, int);

- (void) functionThatTakesACallback: (MyCallback) callback;

在swift中,我正在尝试以这种方式使用它:

self.objcclass!.functionThatTakesACallback()
{
    (values: NSMutableData, length: Int32) -> Void in
        // Do something with this data.
}

我得到的错误是:

无法将 '(NSMutableData, Int32) -> Void' 类型的值转换为预期的参数类型 'MyCallback!'

如果我稍微展开一下,通过将块直接放入 Objective-C 函数定义(无 typedef):

- (void) functionThatTakesACallback: (void (^)(NSMutableData*, int)) callback;

它给了我更多的帮助:

无法将 '(NSMutableData, Int32) -> Void' 类型的值转换为预期的参数类型 '((NSMutableData!, Int32) -> Void)!'

那么,本质上,有没有办法解开这个闭包以适应预期的类型?还是重新定义Objective-C类型?

【问题讨论】:

    标签: objective-c swift objective-c-blocks


    【解决方案1】:

    我认为您需要在回调参数和函数的回调参数中添加可空性属性。有两种方法可以做到。

    将可空性注释添加到每个需要它的地方。

    @interface MyObjCClass : NSObject
    typedef void (^MyCallback)(nonnull NSMutableData*, int);
    
    - (void) functionThatTakesACallback: (nonnull MyCallback) callback;
    

    将整个文件设为非空

    NS_ASSUME_NONNULL_BEGIN
    
    @interface MyObjCClass : NSObject
    typedef void (^MyCallback)(NSMutableData*, int);
    
    - (void) functionThatTakesACallback: (MyCallback) callback;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    【讨论】:

      【解决方案2】:

      我实际上只是设法解决了这个问题,但是由于解决方案很简单,但考虑到错误消息相当不直观,这里是解决方案:

      来自 Swift 的函数调用实际上必须是:

      self.objcclass!.functionThatTakesACallback()
      {
          (values: NSMutableData!, length: Int32!) -> Void in
              // Do something with this data.
      }
      

      【讨论】:

      • 您应该尽量避免使用强制展开 (!),因为通常有一个可选项是有充分理由的。取而代之的是使用? 并测试它是否包含一个值。请参阅my answer 了解如何执行此操作。
      【解决方案3】:

      对于参数values,Objective-C 需要一个指向对象的指针,而该指针可能为 nil。在 Swift 中,它转换为 optional 值。 optional 后跟 ? 并且应该被解包 - 检查 nil 并且如果那里有对象则返回它。

      试试:

      self.objcclass!.functionThatTakesACallback() {
        (values: NSMutableData?, length: Int32) -> Void in
          if let values = values { // first values is a local, second values is unwrapped into it
            // Do something with this data.
          }
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-09
        • 1970-01-01
        • 1970-01-01
        • 2019-03-08
        相关资源
        最近更新 更多