Article

Using Objective-C Runtime Features in Swift Objective-Cランタイム機能をSwiftで使用する

Use selectors and key paths to interact with dynamic Objective-C APIs. セレクタとキーパスを使って動的Objective-C APIと相互作用してます。

Overview 概要

Some Objective-C APIs—like target-action—accept method or property names as parameters, then use those names to dynamically call or access the methods or properties. In Swift, you use the #selector and #keyPath expressions to represent those method or property names as selectors or key paths, respectively. いくつかのObjective-C API — ターゲットアクションのような — は、メソッドまたはプロパティ名を引数として受け入れます、そのときそれらの名前を使って動的にメソッドまたはプロパティに呼び出しまたはアクセスをします。Swiftでは、あなたは#selector#keyPath式を使って、それらメソッドまたはプロパティ名をセレクタまたはキーパスとして表します。

Use Selectors to Arrange Calls to Objective-C Methods セレクタを使ってObjective-Cメソッドへの呼び出しを整える

In Objective-C, a selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure, and you create them using the #selector expression. Ojbective-Cでは、セレクタはObjective-Cメソッドの名前を参照するある型です。Swiftでは、Objective-CセレクタはSelector構造体によって表されます、そしてあなたはそれらを#selector式を使って作成します。

In Swift, you create a selector for an Objective-C method by placing the name of the method within the #selector expression: #selector(MyViewController.tappedButton(_:)). To construct a selector for a property’s Objective-C getter or setter method, prefix the property name using the getter: or setter: label, like #selector(getter: MyViewController.myButton). The example below shows a selector being used as part of the target-action pattern to call a method in response to the touchUpInside event. Swiftでは、あなたはセレクタをObjective-Cメソッドに対して、そのメソッドの名前を#selector式の内部に置くことによって作成します:#selector(MyViewController.tappedButton(_:))。セレクタをあるプロパティの持つObjective-Cゲッターまたはセッターメソッドに対して組み立てるには、プロパティ名にgetter:またはsetter:ラベルを使って接頭辞を付けてください、#selector(getter: MyViewController.myButton)のように。下の例は、ターゲットアクションパターンの一部として使われるセレクタを示して、あるメソッドをtouchUpInsideメソッドに答えて呼び出します。


import UIKit
class MyViewController: UIViewController {
    let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
    
    override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        let action = #selector(MyViewController.tappedButton)
        myButton.addTarget(self, action: action, forControlEvents: .touchUpInside)
    }
    
    @objc func tappedButton(_ sender: UIButton?) {
        print("tapped button")
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}

If you need to disambiguate between overloaded functions, use parenthesized expressions along with the as operator to make the #selector expression refer unambiguously to a specific overload. あなたがオーバーロードされた関数の間の違いを明らかにする必要があるならば、括弧に囲まれた式をas演算子と一緒に使って、#selector式を明白に特定のオーバーロードを参照するようにしてください。

Use Key Paths to Dynamically Access Objective-C Properties キーパスを使って動的にObjective-Cプロパティにアクセスする

In Objective-C, a key is a string that identifies a specific property of an object. A key path is a string of dot-separated keys that specifies a sequence of object properties to traverse. Keys and key paths are frequently used for key-value coding (KVC), a mechanism for indirectly accessing an object’s attributes and relationships using string identifiers. Objective-Cでは、キーはオブジェクトの特定のプロパティを識別する文字列です。キーパスは、辿っていく一連のオブジェクトプロパティを指定する、ドット区切りのキーの文字列です。キーとキーパスは、文字列識別子を使ってオブジェクトの属性および関連付け(リレーションシップ)に間接的にアクセスするための仕組み、キー値コーディング(KVC)のためにしばしば使われます。

You use the #keyPath string expression to create compiler-checked keys and key paths that can be used by KVC methods like value(forKey:) and value(forKeyPath:). The #keyPath string expression accepts chained method or property references. It also supports chaining through optional values within a chain, such as #keyPath(Person.bestFriend.name). Key paths created using the #keyPath string expression don’t pass type information about the properties or methods they reference to the APIs that accept key paths. あなたは、#keyPath文字列式を使って、コンパイラチェック済みのキーおよびキーパスを作成します、それはKVCメソッドvalue(forKey:)value(forKeyPath:)によって使われます。#keyPath文字列式は、数珠つなぎにされたメソッドまたはプロパティ参照を受け入れます。それはまた、連鎖内でオプショナル値を通した連鎖をサポートします、例えば#keyPath(Person.bestFriend.name)など。#keyPath文字列式を使って作成されるキーパスは、それらが参照するプロパティまたはメソッドについての型情報を、キーパスを受け入れるAPIに渡しません。

The example below defines a Person class, creates two instances of it, and uses several #keyPath string expressions to access properties and properties of those properties: 下の例は、Personクラスを定義して、それの2つのインスタンスを作成して、そしていくつかの#keyPath文字列式を使っていくつかのプロパティおよびそれらプロパティのプロパティにアクセスします:


class Person: NSObject {
    @objc var name: String
    @objc var friends: [Person] = []
    @objc var bestFriend: Person? = nil
    
    init(name: String) {
        self.name = name
    }
}
 
let gabrielle = Person(name: "Gabrielle")
let jim = Person(name: "Jim")
let yuanyuan = Person(name: "Yuanyuan")
gabrielle.friends = [jim, yuanyuan]
gabrielle.bestFriend = yuanyuan
 
#keyPath(Person.name)
// "name"
gabrielle.value(forKey: #keyPath(Person.name))
// "Gabrielle"
#keyPath(Person.bestFriend.name)
// "bestFriend.name"
gabrielle.value(forKeyPath: #keyPath(Person.bestFriend.name))
// "Yuanyuan"
#keyPath(Person.friends.name)
// "friends.name"
gabrielle.value(forKeyPath: #keyPath(Person.friends.name))
// ["Yuanyuan", "Jim"]

See Also 参照

Language Interoperability 言語互換性