不推荐在Swift 4模式下使用Swift 3 @objc推理?

Dal*_*leK 478 swift swift4 xcode9-beta

简而言之,在使用Xcode 9 Beta时,我遇到了以下警告:

不推荐在Swift 4模式下使用Swift 3 @objc推理.请解决已弃用的@objc推理警告,使用"使用已弃用的Swift 3 @objc推理"日志记录测试代码,并禁用Swift 3 @objc推理.**

经过一番研究,我仍然不知道如何解决这个问题.我将非常感谢有关如何解决此问题的任何提示以及对正在发生的事情的解释.

我的目标是更好地理解我的代码发生了什么.

Evg*_*nii 794

我通过将目标的"Swift 3 @objc Inference"构建设置更改为"Default"来消除此警告.

在Xcode9中禁用Swift 3 @objc推理

这篇文章:

在Swift 4之前,编译器自动为Objective-C提供了一些Swift声明.例如,如果一个子类来自NSObject,则编译器为这些类中的所有方法创建了Objective-C入口点.该机制称为@objc推理.

在Swift 4中,不推荐使用这种自动@objc推理,因为生成所有Objective-C入口点的成本很高.当"Swift 3 @objc Inference"设置设置为"On"时,它允许旧代码工作.但是,它会显示需要解决的弃用警告.建议"修复"这些警告并将设置切换为"默认",这是新Swift项目的默认设置.

有关更多信息,请参阅此Swift提案.

  • 只是添加 - 您需要为所有构建tagets执行此操作,而不仅仅是项目. (14认同)
  • @DaleK是的,我相信.根据我在回答中提到的Swift提议,objc推断已被弃用."Swift 3 objc Inference"设置仅存在于从旧版Swift迁移的项目中.如果创建一个新项目,则该设置不再存在,这意味着objc推断已关闭.建议解决任何objc推理警告并将其设置为"关闭". (6认同)
  • 谢谢Evgenii.这是一个长期的解决方案吗? (5认同)
  • XCode中的信息消息表明:"在Swift 4模式中使用Swift 3` @ objc`推理已被弃用.请解决已弃用的`@ objc`推理警告,**使用"弃用的Swift 3` @测试您的代码objc`inference"logging enabled**,并禁用Swift 3` @ objc`推理." 知道在哪里启用上述Swift 3` @ objc`推理日志记录? (4认同)
  • @courteouselk,根据Swift提议,可以将SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT环境变量设置为1到3之间的值,以查看日志中Objective-C入口点的用法. (4认同)

kga*_*dis 262

- 什么是@objc推论?到底是怎么回事?

Swift 3,编译器@objc在很多地方推断,所以你不必这样做.换句话说,它确保@objc为您添加!

Swift 4,编译器不再这样做(同样多).您现在必须@objc明确添加.

默认情况下,如果您有一个Swift 4之前的项目,您将收到有关此问题的警告.在Swift 4项目中,您将遇到构建错误.这是通过SWIFT_SWIFT3_OBJC_INFERENCE构建设置来控制的.在Swift 4之前的项目中,这将设置为On.我建议将其设置为Default(或Off),这是新项目的默认选项.

转换所有内容需要一些时间,但由于它是Swift 4的默认设置,因此值得这样做.

- 如何停止编译器警告/错误?

有两种方法可以转换代码,因此编译器不会抱怨.

一种是@objc在每个需要暴露给Objective-C运行时的函数或变量上使用:

@objc func foo() {

}
Run Code Online (Sandbox Code Playgroud)

另一种是@objcMembers通过Class声明来使用.这确保自动添加@objc到类中的所有函数和变量.这是一种简单的方法,但它有成本,例如,它可以通过暴露不需要公开的函数来增加应用程序的大小.

@objcMembers class Test {

}
Run Code Online (Sandbox Code Playgroud)

- 这是什么@objc以及为什么有必要?

如果向Swift类引入新方法或变量,则将它们标记为@objc将它们公开给Objective-C运行时.当您拥有使用Swift类的Objective-C代码时,或者如果您使用的是Objective-C类型的功能时,这是必需的Selectors.例如,目标 - 行动模式: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- 为什么我不会标记一切@objc

标记为@objc:

  • 应用程序二进制大小增加
  • 没有功能重载

请记住,这是一个非常高级的摘要,它比我写的更复杂.我建议阅读实际提案以获取更多信息.

资料来源:

  • 还有其他方法可以为按钮添加操作吗?如果`@ objc`描述了我们必须使用的东西? (7认同)
  • @Stefan是的,可能会有很多转换.将其分成几个阶段.将`SWIFT_SWIFT3_OBJC_INFERENCE`留在`On`.转换为Swift 4.然后处理`@objc`的东西.为简单起见,请遵循以下基本规则:如果在Objc-C代码中使用Swift类(通过桥接头),请使用`@objcMembers`,否则,逐个添加`@objc`.只需使用Xcode搜索来确定是否从任何`.m`文件中调用Swift类.这应该使转换相对无痛. (5认同)
  • @DaleK这应该是接受的答案.抑制警告并让事情像在Swift 3中一样工作是一种选择,但恕我直言并不是最好的选择.重要的是要理解为什么`@ objc`在Swift 4中改变然后*然后*决定修复项目并保持相同. (5认同)
  • 很好的解释和感谢清楚我 (2认同)
  • 感谢您的简短解释 (2认同)

Has*_*leb 48

Migrator无法识别所有需要@objc 推断的Objective-C thunks标记为已弃用的函数以帮助您找到它们
•构建有关已弃用方法的警告
•运行不推荐的thunk时的控制台消息

在此输入图像描述


Dmi*_*try 11

我在"Swift 3 @objc推理"="默认"设置下发出此警告.然后我意识到这是为项目设定的 - 而不是针对目标.因此,请确保目标中有"默认"设置以消除警告.


ing*_*nti 8

您可以简单地传递到"默认"而不是"开启".似乎更符合Apple逻辑.

(但关于使用@obj遗骸的所有其他评论都是有效的.)


Kar*_*tor 7

实际上,你可以通过禁用Swift 3 @objc推理来消除这些警告.但是,可能会出现微妙的问题.例如,KVO将停止工作.这段代码在Swift 3下完美运行:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}
Run Code Online (Sandbox Code Playgroud)

迁移到Swift 4并将"Swift 3 @objc推理"设置为默认值后,我项目的某些功能停止工作.我花了一些调试和研究来找到解决方案.根据我的最佳知识,以下是选项:

  • 启用"Swift 3 @objc推理"(仅当您从Swift 3迁移现有项目时才有效) 在此输入图像描述
  • 将受影响的方法和属性标记为@objc 在此输入图像描述
  • 使用@objcMembers重新启用整个类的ObjC推理 在此输入图像描述

重新启用@objc推理会留下警告,但这是最快的解决方案.请注意,它仅适用于从早期Swift版本迁移的项目.另外两个选项更加繁琐,需要进行一些代码挖掘和大量测试.

另见https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md


小智 7

您可以尝试“Pod update”和/或“flutter clean”

我也在 xcode 中设置了这个设置。

Objective-C接口设置如下:

ObjectiveC接口设置


rad*_*vus 5

我是偶然的iOS开发人员(不久以后会更多),但我仍然找不到其他答案指导的设置(因为我没有答案显示的那个Keychain项),所以现在我发现了,我可能只是在快照中添加了需要单击并找到的突出显示的位置。

  1. 从左上方开始
  2. 选择项目文件夹图标
  3. 在项目文件夹图标下选择您的主项目名称。
  4. 选择右侧的“构建设置”。
  5. 在“目标”下选择您的项目。
  6. 向下滚动很远(或在搜索文本框中搜索单词推断)

查找设置