Swift 4モードでのSwift 3 @objc推論の使用は非推奨ですか?


485

簡単に言うと、Xcode 9 Betaを使用しているときに、次の警告が表示されました。

Swift 4モードでのSwift 3 @objc推論の使用は非推奨です。非推奨の@objc推論の警告に対処し、「非推奨のSwift 3 @objc推論の使用」ログを有効にしてコードをテストし、Swift 3 @objc推論を無効にしてください。**

いくつかの調査の後、私はまだ問題を修正する方法を知りません。この問題を解決するためのヒントと、何が起こっているのかについての説明をいただければ幸いです。

私の目標は、コードで何が起こっているかをよりよく理解することです。


4
警告メッセージから、どのオブジェクトがそれを引き起こしているのかはわかりません。Xcodeは、そのオブジェクトがどの行にあるかを単純に示しません。この警告がどこから来ているのかを知るためのアドバイスはありますか?
olyv 2018年

回答:


816

ターゲットの「Swift 3 @objc Inference」ビルド設定を「デフォルト」に変更することで、この警告を取り除きました。

Xcode9でSwift 3 @objc推論を無効にする

この記事から:

Swift 4以前は、Objective-CでSwift宣言が自動的に利用できるようにコンパイラーが作成していた。たとえば、1つがNSObjectからサブクラス化された場合、コンパイラはそのようなクラスのすべてのメソッドに対してObjective-Cエントリポイントを作成しました。このメカニズムは@objc推論と呼ばれます。

Swift 4では、これらのObjective-Cエントリポイントをすべて生成するのはコストがかかるため、このような自動@objc推論は非推奨です。「Swift 3 @objc Inference」設定を「オン」に設定すると、古いコードが機能するようになります。ただし、対処する必要がある非推奨の警告が表示されます。これらの警告を「修正」し、設定を「デフォルト」切り替えることをお勧めします。これは、新しいSwiftプロジェクトのデフォルトです。

詳細については、このSwiftの提案も参照してください。


5
エフゲニーありがとうございます。これは長期的な解決策ですか?
DaleK 2017

6
@DaleKはい、そう思います。私の回答で述べたSwiftの提案によると、objc推論は非推奨です。設定「Swift 3 objc Inference」は、古いバージョンのSwiftから移行されたプロジェクトにのみ存在します。新しいプロジェクトを作成すると、その設定は存在しなくなります。つまり、objc推論はオフになります。objc推論の警告に対処し、それを「オフ」に設定することをお勧めします。
Evgenii 2017

4
XCodeの情報メッセージは、「@objcSwift 4モードでのSwift 3 推論の使用は非推奨です。非推奨の@objc推論警告に対処し、「非推奨のSwift 3 @objc推論の使用」ロギングを有効にしてコードをテストし、Swift 3 推論を無効にしてください@objc。」上記のSwift 3 @objc推論ロギングをどこで有効にするか考えていますか?
courteouselk 2017

4
@ courteouselk、Swiftの提案によると、SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT環境変数を1〜3の値に設定して、ログのObjective-Cエントリポイントの使用状況を確認できます。
Evgenii 2017年

14
追加するだけ-プロジェクトだけでなく、すべてのビルドタグレットに対してこれを行う必要があります。
Krivvenz 2017

270

- @objc推論とは何ですか?何が起こっている?

ではSwift 3、コンパイラーは@objc多くの場所で推論を行うので、そうする必要はありません。言い換えれば、それは@objcあなたのために追加することを確認します!

ではSwift 4、コンパイラーは(これほど)これを行わなくなりました。ここで@objc明示的に追加する必要があります。

デフォルトでは、Swift 4以前のプロジェクトがある場合、これに関する警告が表示されます。Swift 4プロジェクトでは、ビルドエラーが発生します。これは、SWIFT_SWIFT3_OBJC_INFERENCEビルド設定によって制御されます。Swift 4以前のプロジェクトでは、これはに設定されていOnます。これをDefault(またはOff)に設定することをお勧めします。これは、新しいプロジェクトのデフォルトのオプションです。

すべてを変換するにはしばらく時間がかかりますが、Swift 4のデフォルトであるため、実行する価値があります。

-コンパイラの警告/エラーを停止するにはどうすればよいですか?

コンパイラーが文句を言わないようにコードを変換する方法は2つあります。

1つは@objc、Objective-Cランタイムに公開する必要がある各関数または変数で使用することです。

@objc func foo() {

}

もう1つは宣言で使用@objcMembersすることClassです。これにより、クラス内のすべての関数と変数が自動的に追加@objcされます。これは簡単な方法ですが、コストがかかります。たとえば、公開する必要がなかった関数を公開することで、アプリケーションのサイズを増やすことができます。

@objcMembers class Test {

}

-何で@objc、なぜ必要なのですか?

Swiftクラスに新しいメソッドまたは変数を導入する場合は、@objcそれらをObjective-Cランタイムに公開するものとしてマークします。これは、Swiftクラスを使用するObjective-Cコードがある場合、またはのようなObjective-Cタイプの機能を使用している場合に必要ですSelectors。たとえば、target-actionパターン: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

-なぜすべてをマークしないの@objcですか?

何かを@objc次のようにマークすると付属するネガがあります:

  • アプリケーションのバイナリサイズの増加
  • 関数のオーバーロードなし

これは非常に高レベルの要約であり、私が書いたよりも複雑であることを覚えておいてください。詳細については、実際の提案を読むことをお勧めします。

出典:


@objc動的ディスパッチを意味するものではないため、Swiftは静的または仮想ディスパッチを自由に使用できます(結果として異なるコードを実行する可能性があります)。dynamicSwiftに動的ディスパッチを使用させるには、このキーワードが必要です。
ケビン2017

7
ボタンにアクションを追加する他の方法はありますか?@objc値下げした場合、何を使用する必要がありますか?
Aznix 2017

5
@Stefanはい、変換するのにかなりの時間がかかる場合があります。ステージに分割します。に出発SWIFT_SWIFT3_OBJC_INFERENCEOnます。Swift 4に変換します。次に、それに取り組む@objc。簡単にするために、基本的なルールに従います。SwiftクラスがObjc-Cコードで(ブリッジングヘッダー経由で)使用@objcMembersされている場合は、を使用します。それ以外の場合は、1つずつ追加し@objcます。Xcode検索を使用して、Swiftクラスが任意の.mファイルから呼び出されているかどうかを確認します。これにより、変換が比較的簡単になります。
kgaidis 2017

5
@DaleKこれは受け入れられるべき答えです。警告を抑制し、Swift 3のように機能させることはオプションですが、IMHOは最良のものではありません。それはなぜ理解することが重要です@objcスウィフト4の変化をし、その後、修正プロジェクトに決定を下すと同じそれを保ちます。
derpoliuk 2017年

2
この短い説明をありがとう
Schmoudi 2018

48

移行が必要なすべての機能を識別することはできません@objc 推論のObjective-Cは、としてマークされたサンク非推奨あなたがそれらを見つけることが
推奨されないメソッドについて•ビルドの警告
非推奨サンクを実行しているとき•コンソールメッセージを

ここに画像の説明を入力してください


1
では、@ objcをどうすればよいでしょうか。それを除く?それを残しますか?私はすでにそれを削除しました。そして、私はそれらの警告を受けたので、それらを追加する必要がありますか?ステップ3でそれをどうすればいいですか?
Shial

funcの直前に@objcを追加
Hassan Taleb

1
ステップ3とは何ですか?いくつかの説明を追加できます:)
Shial

そして私の場合、この警告が表示されますが、コードが指定されていません。@objcとマークされた2つのメソッドがあり、それらはそれを必要とする唯一のメソッドのようです。デフォルトに変更しても、コンパイル中に警告が表示されます。
モーリーマルコヴィッツ2018年

12

「Swift 3 @objc Inference」=「デフォルト」設定でこの警告が出ました。それから、それがプロジェクトではなく、ターゲットに設定されていることに気付きました。したがって、警告を取り除くために、ターゲットに「デフォルト」設定があることを確認してください。


プロジェクト設定でデフォルトに変更した後でも、エラーを解決するために20分無駄になりました。ターゲットでも変更する必要があることを正確に指摘しました。
SkrewEverything

8

"ON"の代わりに "default"に渡すだけです。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バージョンから移行したプロジェクトでのみ使用できることに注意してください。他の2つのオプションはより退屈で、コードの掘り起こしと広範なテストが必要です。

https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.mdも参照してください。


7

私はときどきiOS開発者ですが(間もなくもっと増えます)、他の回答でガイドされている設定をまだ見つけることができませんでした(回答が示すキーチェーンアイテムを持っていなかったため)。このスナップショットを追加して、クリックして見つける必要があるハイライトされた場所を追加するだけです。

  1. 左上から
  2. プロジェクトフォルダアイコンを選択します
  3. プロジェクトフォルダアイコンの下にあるメインプロジェクト名を選択します。
  4. 右側のビルド設定を選択します。
  5. TARGETSでプロジェクトを選択します。
  6. 一番下までスクロール(または検索テキストボックスで単語推論を検索)

設定を見つける


6

「ポッド更新」や「フラッタークリーン」を試すことができます

xcodeでもこの設定を行いました。

Objective-Cインターフェイスの設定は次のとおりです。

ObjectiveCインターフェース設定


2

Swift 3 @objc推論Swift 4モードでのSwift 3 @objc推論の使用は非推奨です。非推奨の@objc推論の警告に対処し、「非推奨のSwift 3 @objc推論の使用」ログを有効にしてコードをテストし、「Swift 3 @objc Inference」ビルド設定を「XMLParsingURL」の「デフォルト」に変更して推論を無効にしてください目標。

に着いた

  1. 最初のステップはビルド設定です

  2. 検索して設定の推論を構築する

  3. swift 3 @objc推論のデフォルトを変更

ここに画像の説明を入力してください


1

完了するまでテスト待機を実行するだけで済みます。その後、ビルド設定に移動し、ビルド設定の推論を検索して、swift 3 @objc Inferenceを(デフォルト)に変更します。それは私がやったことと完璧に働いたことのすべてです。


0

Swift 4モードでのSwift 3 @objc推論の使用は非推奨ですか?

func call @objcを使用

func call(){

foo()

}

@objc func foo() {

}

0

@wisekiddoが言ったことに加えて、特に他の環境から来ている場合は、ビルドフレーバー(つまり、デバッグとリリース)のproject.pbxprojようにSwift 3 @obj推論をデフォルトに設定することにより、ファイルのビルド設定を変更することもできSWIFT_SWIFT3_OBJC_INFERENCE = Default;ます。 Xcode以外

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.