【问题标题】:unrecognized selector sent to instance after Swift 4.2 migrationSwift 4.2 迁移后发送到实例的无法识别的选择器
【发布时间】:2020-03-04 15:15:07
【问题描述】:

我刚刚将我的项目从 Swift 3.0 迁移到 Swift 4.2,我开始收到此错误。

同一个方法被多个类调用,但只有一个抛出异常。任何想法在 Swift 迁移期间可能导致此问题的单个类中可能发生的变化?

2020-03-04 09:53:42.552405-0500 湖观察者[13974:1234549] -[Lake_Observer.LocationChangeController reusablePickerViewController:didChooseValue:forCtrl:]:无法识别 选择器发送到实例 0x1040ca800 2020-03-04 09:53:42.554410-0500 Lake Observer[13974:1234549] *** 由于未捕获而终止应用程序 异常“NSInvalidArgumentException”,原因: '-[Lake_Observer.LocationChangeController reusablePickerViewController:didChooseValue:forCtrl:]: 无法识别 选择器发送到实例 0x1040ca800'

这是发生异常的地方。 (RecorderReusablePicker)

- (void) buttonIsPressed:(UIButton *)paramSender{

        NSMutableArray *retArray = [[NSMutableArray alloc] initWithCapacity:array.count];
        for (int i = 0; i < array.count; i++) {
            [retArray addObject:[NSNumber numberWithInteger:[genericPicker selectedRowInComponent:i]]];
        }
        [callingReference reusablePickerViewController:self didChooseValue:[[RecorderReusableResult alloc] initWithArray:retArray clearValue:NO] forCtrl:callingControlReference];
}

选择器在此处创建。 (LocationChangeController)

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {

    if (textField == editTextWaterBody) {
        let waterbodyArray: NSArray? = NSArray(objects: waterbodyNames)
        self.view.window?.rootViewController?.present(RecorderReusablePicker (dataArray: waterbodyArray as? [Any], widthArray: nil, inInitialIndexArray: [savedWaterbodyIndex], reference: self, andControlRef: editTextWaterBody, andTitle: "Please select your waterbody", showSelection: true, allowPanZoom: false), animated: true, completion: nil)
        return false
    }

    return true
}

以及从picker返回时的方法。

func reusablePickerViewController(_ reusablePickerViewController: RecorderReusablePicker!, didChooseValue retVal: RecorderReusableResult!, forCtrl outCtrl: Any!) {
    reusablePickerViewController.dismiss(animated: true, completion: nil)
}

同样,还有其他类具有完全相同的方法来从 Picker 创建和返回,但只有一个会导致异常。

【问题讨论】:

  • 如果您将func reusablePickerViewController 更改为@objc func reusablePickerViewController 会解决问题吗?
  • 是的,先生,确实如此。非常感谢。
  • 这很有意义,因为我的 LocationChangeController 类的前缀为 @objc,但其他类没有
  • 那太好了,我会给出这个答案。可能对其他人有用...

标签: ios swift swift4.2


【解决方案1】:

改变

func reusablePickerViewController

@objc func reusablePickerViewController

从 Swift 3 到 Swift 4.2 的迁移改变了实例成员如何暴露给 Objective-C 的规则。在 Swift 3 中,它们默认是公开的。在 Swift 4.2 中,您必须显式地公开它们;否则,Objective-C 无法看到它们——这正是发生在你身上的事情。该方法存在,但 Objective-C 认为它不存在,因此它因无法识别的选择器异常而崩溃。

【讨论】:

  • 作为后续问题,有没有办法确定我的代码中可能需要明确公开哪些其他方法?
  • 所有尚未公开的内容都必须明确公开。 “已经暴露”是指,例如,像 viewDidLoad 这样的东西已经暴露,因为它是 UIViewController 方法的覆盖,并且 UIViewController 已经 属于 Objective-C / Cocoa,所以它知道它。默认情况下,您编写的任何 not 覆盖和 not 在 Objective-C 协议中声明的内容都是隐藏的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
  • 2018-04-24
相关资源
最近更新 更多