Swiftで@objcを使用するのはいつですか?


87

Swiftでは、次のような方法がいくつかあります。

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)

@objcをいつ使用するのか疑問に思いましたか?いくつかのドキュメントを読みましたが、Objective-Cで呼び出し可能にする場合は、@ objcフラグを追加する必要があると言われています。

ただし、これはSwiftのプライベート関数です。@ objは何をしますか?


1
いい質問!!!
ErhanDemirci19年

回答:


67

プライベートとは、Swiftでのみ表示されることを意味します。したがって、@ objcを使用してObjective-Cに表示します。プライベート関数をすばやく選択する関数がある場合は、それが必要です。

@objc属性は、SwiftAPIをObjective-CおよびObjective-Cランタイムで使用できるようにします。

参照:https//developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html


1
だから、@objc private func doubleTapGestureRecognized@ objcとprivateの両方を持つことのポイントは何ですか?Objective-CクラスがdoubleTapGestureRecognizedを上書きできると言っていますか?
Wingzero 2015年

1
obj-cではとにかく任意のメソッドを上書きできるからだと思います。
奇妙な時間2015

2
この答えがどのように正しいかわからず、彼のQに答えます。ここで提供されている回答はすでに彼のQ自体に含まれています。 Qは「これはswiftのプライベート関数です。\ @ objは何をしますか?」
KBJ

3
リンクが壊れます。特にAppleのドキュメントに。こちらのドキュメントから重要な要素を抽出することを検討してください。
levigroker

55

別の遅い回答ですが、この質問に対する既存の回答はどれも、OPの質問に実際には答えていません。つまり、Objective-Cとの対話のためにある場合@objcprivateクラス@objcのメンバーと問題のメンバーで一体何を使用する必要があるのでしょうか。プライベートです。つまり、プロジェクトにObjective-Cコードが含まれていても、とにかくメンバーを表示できないようにする必要がありますか?

その理由は、フレームワークの多くがObjective-Cで記述されているため、特定のAPIと対話するためにObjective-C機能が必要になる場合があるためです。

たとえば、次の方法で通知を登録するとしますDistributedNotificationCenter

DistributedNotificationCenter.default.addObserver(self,
                                                  selector: #selector(somethingHappened(_:)),
                                                  name: someNotification,
                                                  object: nil)

これが機能するためには、のセレクターを取得できる必要があります somethingHappenedメソッドの。ただし、セレクターはObjective-Cの概念であるため、メソッドがObjective-Cに表示されない場合、セレクターはありません。したがって、メソッドがプライベートであり、任意の外部コードによって呼び出されるべきではない場合でも、Objective-Cで記述され@objcDistributedNotificationコードがセレクターを介して呼び出すことができるようにするには、メソッドが必要になります。

別の一般的なケース @objc必要となるは、特にmacOSでKey-Valueコーディング(KVC)をサポートすることです KVCとKVOを使用してCocoaバインディングを実装します。KVCは、Cocoaの他の多くのシステムと同様に、Objective-Cで実装されています。これには、KVC準拠のプロパティをObjective-Cランタイムに公開する必要があるという効果があります。KVC準拠のプロパティをプライベートにすることが理にかなっている場合があります。1つの例は、他のプロパティに影響を与えるプロパティがある場合です。

@objc private dynamic var originalProperty: String

@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
    #keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }

この場合には、当社の実際の保存された施設には、プライベートですが、我々は依存プロパティ、ない外部のコードを公開するには、私有財産が更新されたときにその通知を送信する必要があります。プライベートプロパティをとしてマークする@objcことで、KVC依存関係を設定することで簡単にそれを行うことができます。そうでない場合は、プライベートプロパティwillSetdidSetハンドラーで通知を手動で送信するコードを記述する必要があります。さらに、KVCシステムに次のことを通知する静的プロパティdependentProperty依存しoriginalPropertyそれを見つけて呼び出すために、Objective-Cに公開する必要がありますが、コードのクライアントには関係ありません。

また、実装の詳細としてCocoa Bindingsを使用してビュー内のコントロールを更新するmacOSアプリのビューコントローラーは、特定のプライベートプロパティをKVCに準拠させて、それらのコントロールをそれらにバインドする場合があります。

ご覧のとおり、フレームワークと対話するために、コードのクライアントに表示される必要はなく、メソッドまたはプロパティをObjective-Cに公開する必要がある場合があります。


25

@ objc /ダイナミック

互換性のためです:Swiftファイル/コードをObjective-Cベースのプロジェクトにインポートしたら。

プロパティ/メソッドにObjective-Cコードまたはクラスからアクセスできるようにする場合は、これを使用します。

ほとんどの場合、Objective-C基本クラスのSwiftクラスをサブクラス化するときに発生します。

Swiftクラスまたはプロトコルは、Objective-Cでアクセスおよび使用できるように、@ objc属性でマークする必要があります。この属性は、このSwiftコードにObjective-Cからアクセスできることをコンパイラーに通知します。SwiftクラスがObjective-Cクラスの子孫である場合、コンパイラーは自動的に@objc属性を追加します。

ここにについて述べているアップルのドキュメント@objc

Objective-CのSwiftを使用する

言語相互運用性の互換性

リンクの更新:
リンクがアップルによって更新されたようです。


11

@objcはクラス属性なので、

@objc public class MyClass

クラスのメソッドをObjectiveCクラスに公開するため、クラスにパブリック関数が含まれている場合にのみ使用します。


7

遅い答えですが、これ @objc動作はSwift 4(Xcode 9でリリースされました。これは通常10日前にリリースされました)の時点でわずかに変更されています。

Swift 4では、のいくつかの推論ケース@objcが削除されています。これは、いくつかの追加のケースでは、@objcヘッダーがSwiftコンパイラーによって推測される Swift4では推測されます。

についてのSwift進化の提案でもっと読む この変更

すでに述べたように、一般的に@objcは、特定のメソッドをObjective-Cランタイムに公開します。これは、Swiftの言語の相互運用性の一部です。


1
だから、これがSwift 4にアップデートした後、ObjCからいくつかの変数にアクセスできない理由ですよね?Swift 3.Xでは、追加する必要はありませんでした@objc
rgkobashi 2018年

ああ、わかりました、他の誰かと再確認することは常に良いことです、ありがとう!
rgkobashi 2018年

1

@objc宣言をに公開しObjective-C runtimeます。#selectorObjective-Cランタイムを使用するためのSwiftの機能を見てみましょう。この場合、Swiftを定義することができます@objc private func[詳細]

Objective-CからSwiftの機能を使用するには:

  1. Swiftのクラスはから拡張する必要があります NSObject
  2. マークスウィフトの:

    a。@objcMembers クラスのみ-すべての public コンストラクターフィールド、およびメソッドを公​​開ます。サブクラスにも適用可能

    b。@objc クラス/列挙型/プロトコル構造体を除く)[名前付きタイプ]

    • @objc クラス(オプション)-デフォルト を公​​開しますpublic init()。または@objc(<custom_name>)、クラスのカスタム名を設定します。
    • @objc コンストラクターフィールドメソッド-それらを選択的に公開する

Swiftのメソッドは、次の名前で使用できるようになります。

<swiftName>With<firstArgument>:<secondArgument>:

例えば:

public func printHelloWorld(arg1: String, arg2:String)
//is reached through: 
[someObject printHelloWorldWithArg1: arg2:];

[@objcdynamic]

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