不建议在Swift 4模式下使用Swift 3 @objc推论吗?


485

简要地说,在使用Xcode 9 Beta时,我遇到了以下警告:

不建议在Swift 4模式下使用Swift 3 @objc推断。请解决已弃用的@objc推断警告,启用“使用已弃用的Swift 3 @objc推断”日志记录来测试您的代码,并禁用Swift 3 @objc推断。**

经过研究后,我仍然不知道如何解决该问题。我将不胜感激有关如何解决此问题的所有技巧以及对所发生情况的解释。

我的目标是更好地理解我的代码正在发生的事情。


4
我并不是真正从警告消息中得知是哪个原因引起的。Xcode只是不说该对象在哪一行。有什么建议如何找出此警告来自何处?
olyv '18年

Answers:


816

我通过将目标的“ Swift 3 @objc Inference”构建设置更改为“ Default”来摆脱此警告。

在Xcode9中禁用Swift 3 @objc推断

这篇文章

在Swift 4之前,编译器自动将一些Swift声明提供给Objective-C。例如,如果从NSObject继承了一个子类,则编译器会为此类中的所有方法创建Objective-C入口点。该机制称为@objc推断。

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

另请参阅此Swift提议


5
谢谢叶夫根尼。这是一个长期的解决方案吗?
DaleK

6
@DaleK是的,我相信是的。根据我在回答中提到的Swift提议,不建议使用objc推断。设置“ Swift 3 objc Inference”仅在从较早版本的Swift迁移的项目中存在。如果创建一个新项目,则该设置不再存在,这意味着objc推断已关闭。建议解决所有objc推断警告并将其设置为“关”。
Evgenii

4
XCode中的信息消息表明:“不建议@objc在Swift 4模式下使用Swift 3 推断。请解决不建议使用的@objc推断警告,启用“使用不建议使用的Swift 3 @objc推断”日志记录来测试代码,并禁用Swift 3 @objc推断。” 任何想法在哪里启用所说的Swift 3 @objc推理日志记录?
Courteouselk

4
@courteouselk,根据Swift的建议,可以将SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT环境变量设置为1到3的值,以查看日志中Objective-C入口点的用法。
Evgenii

14
只是添加-您需要对所有构建标记执行此操作,而不仅是项目。
Krivvenz

270

-什么是@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() {

}

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

@objcMembers class Test {

}

-什么是@objc,为什么有必要?

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

-为什么我不标记所有内容@objc

标记为@objc

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

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

资料来源:


@objc并不意味着动态调度,Swift可以自由使用静态或虚拟调度(并可能执行不同的代码)。该dynamic关键字是必需的强制斯威夫特使用动态调度。
凯文

7
还有其他方法可以向按钮添加操作吗?如果描述@objc了我们必须使用什么?
Aznix

5
@Stefan是的,可能要转换很多。将其分为多个阶段。SWIFT_SWIFT3_OBJC_INFERENCE在出发On。转换为Swift4 @objc。然后解决问题。为了简单起见,请遵循基本规则:如果在Objc-C代码中使用Swift类(通过桥接标头),请使用@objcMembers,否则,一个接一个地添加@objc。只需使用Xcode搜索来查找是否从任何.m文件中调用了Swift类。这应该使转换相对简单。
kgaidis

5
@DaleK这应该被接受的答案。禁止警告并使其像Swift 3一样正常工作是一种选择,但是恕我直言,不是最好的选择。重要的是要了解为什么@objc在Swift 4中进行了更改,然后决定修复项目并保持不变。
derpoliuk

2
感谢您的简短解释
Schmoudi

48

迁移无法识别所有需要的功能@objc 推断的Objective-C的thunk被标记为不推荐使用,以帮助您找到他们
•建立有关不赞成的方法警告
•控制台消息时运行过时的thunk

在此处输入图片说明


1
那么@objc应该怎么做?去掉它?别管它?我已经删除了。并且我收到了那些警告,所以我必须添加它们?我应该在第3步中这样做吗?
Shial

在func之前添加@objc
Hassan Taleb

1
第三步是什么?您可以添加一些描述:)
Shial

就我而言,我得到此警告,但没有代码指向。有两种标记为@objc的方法,它们似乎是唯一需要它的方法。我将其更改为Default,并且在编译期间仍收到警告。
莫里·马克维兹

12

我使用“ Swift 3 @objc Inference” =“默认”设置发出了此警告。然后我意识到这是为项目设置的-不是针对目标的。因此,请确保您的目标中具有“默认”设置以摆脱警告。


即使在项目设置中更改为“默认”后,我也浪费了20分钟的时间来寻求解决错误的方法。您恰好指出了它也需要更改目标。
SkrewEverything

8

您可以简单地传递给“默认”而不是“开”。似乎更遵守Apple的逻辑。

(但其他有关使用的评论@obj仍然有效。)


7

确实,通过禁用Swift 3 @objc Inference可以消除这些警告。但是,细微的问题可能会弹出。例如,KVO将停止工作。这段代码在Swift 3下完美运行:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}

迁移到Swift 4并将“ Swift 3 @objc Inference”设置为默认值后,我项目的某些功能停止工作。我花了一些调试和研究才能找到解决方案。据我所知,以下是选项:

  • 启用“ Swift 3 @objc Inference”(仅当您从Swift 3迁移现有项目时才有效) 在此处输入图片说明
  • 将受影响的方法和属性标记为@objc 在此处输入图片说明
  • 使用@objcMembers为整个类重新启用ObjC推断 在此处输入图片说明

重新启用@objc推断会使您得到警告,但这是最快的解决方案。请注意,它仅适用于从早期Swift版本迁移的项目。其他两个选项比较繁琐,需要进行一些代码挖掘和大量测试。

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


7

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

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

查找设置


6

您可以尝试“ Pod更新”和/或“干净”

我也在xcode中设置了此设置。

Objective-C界面设置如下:

ObjectiveC界面设置


2

Swift 3 @objc推定不建议在Swift 4模式下使用Swift 3 @objc推论。请解决已弃用的@objc推断警告,在启用“使用已弃用的Swift 3 @objc推断”记录的情况下测试您的代码,然后通过将“ XMLParsingURL”的“ Swift 3 @objc推断”构建设置更改为“默认”来禁用推断。目标。

到了

  1. 第一步获得构建设置

  2. 搜索以进行构建设置推断

  3. 快速更改3 @objc推断默认

在此处输入图片说明


1

您只需要运行测试直到完成,之后转到Build Setting,搜索到Build Setting Inference,将swift 3 @objc Inference更改为(默认)。这就是我所做的一切,并且工作得非常完美。


0

不建议在Swift 4模式下使用Swift 3 @objc推论吗?

使用func调用@objc

func call(){

foo()

}

@objc func foo() {

}

0

除了@wisekiddo所说的之外,您还可以project.pbxproj通过将Swift 3 @obj Inference设置为默认值来修改文件中的构建设置,就像SWIFT_SWIFT3_OBJC_INFERENCE = Default;您的构建风格(例如,调试和发布)一样,特别是如果您来自其他环境除了Xcode

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.