私はグーグルしましたが、SwiftのrespondsToSelector:
に相当するものが何かを見つけることができませんでした。
これが私が見つけることができる唯一のものです( respondsToSelector: に代わるものとして)デバイス上で実行しているときに新しいAPIが存在するかどうかを確認し、存在しない場合は以前のバージョンのAPIにフォールバックします。
前述のように、Swiftではほとんどの場合、必要なものは?
オプションのアンラッパー演算子を使用して達成できますこれにより、オブジェクトが存在し(nil
ではなく)、そのメソッドが実装されている場合に限り、そのオブジェクトに対してメソッドを呼び出すことができます。
まだrespondsToSelector:
が必要な場合は、NSObject
プロトコルの一部としてまだ存在しています。
SwiftでObj-C型のrespondsToSelector:
を呼び出している場合は、期待どおりに機能します。自分のSwiftクラスでそれを使用している場合は、クラスがNSObject
から派生していることを確認する必要があります。
これは、Swiftクラスがセレクタに応答するかどうかを確認できる例です。
class Worker : NSObject
{
func work() { }
func eat(food: AnyObject) { }
func sleep(hours: Int, minutes: Int) { }
}
let worker = Worker()
let canWork = worker.respondsToSelector(Selector("work")) // true
let canEat = worker.respondsToSelector(Selector("eat:")) // true
let canSleep = worker.respondsToSelector(Selector("sleep:minutes:")) // true
let canQuit = worker.respondsToSelector(Selector("quit")) // false
パラメータ名を省略しないでください。この例では、Selector("sleep::")
はnotSelector("sleep:minutes:")
と同じです。
本当のSwiftの置き換えはありません。
次の方法で確認できます。
someObject.someMethod?()
これは、メソッドsomeMethod
がオブジェクトsomeObject
で定義されている場合にのみ呼び出されますが、メソッドをoptional
として宣言している@objc
プロトコルに対してのみ使用できます。
Swiftは本質的に安全な言語なので、Swiftはメソッドを呼び出すたびにそのメソッドがあることを知っている必要があります。実行時検査はできません。ランダムオブジェクトに対してランダムメソッドを呼び出すだけではいけません。
Obj-CでもARCではうまく動作しないので、可能であればこのようなことは避けるべきです(ARCはperformSelector:
に対して警告を発します)。
しかしながら、利用可能なAPIをチェックするとき、もしあなたがNSObject
インスタンスを扱っていれば、SwiftであってもrespondsToSelector:
を使うことができます:
@interface TestA : NSObject
- (void)someMethod;
@end
@implementation TestA
//this triggers a warning
@end
var a = TestA()
if a.respondsToSelector("someMethod") {
a.someMethod()
}
Swift 3シンタックスの2017年3月20日更新:
オプションのメソッドが存在するかどうか気にしないのであれば、delegate?.optionalMethod?()
を呼び出してください。
それ以外の場合は、おそらくguard
を使用するのが最善の方法です。
weak var delegate: SomeDelegateWithOptionals?
func someMethod() {
guard let method = delegate?.optionalMethod else {
// optional not implemented
alternativeMethod()
return
}
method()
}
元の回答:
このようなオプションのプロトコルをテストするために "if let"アプローチを使うことができます。
weak var delegate: SomeDelegateWithOptionals?
func someMethod() {
if let delegate = delegate {
if let theMethod = delegate.theOptionalProtocolMethod? {
theMethod()
return
}
}
// Reaching here means the delegate doesn't exist or doesn't respond to the optional method
alternativeMethod()
}
プロトコルをNSObjectProtocolのサブプロトコルとして定義する必要があるようです... respondsToSelectorメソッドを取得します。
@objc protocol YourDelegate : NSObjectProtocol
{
func yourDelegateMethod(passObject: SomeObject)
}
@objcを指定するだけでは不十分であることに注意してください。実際のデリゲートがNSObjectのサブクラスであることにも注意する必要があります - Swiftではそうではないかもしれません。
テストしているメソッドが@ objcプロトコルでオプションのメソッドとして定義されている場合(あなたの場合のように聞こえます)、次に、オプションの連鎖パターンを次のように使用します。
if let result = object.method?(args) {
/* method exists, result assigned, use result */
}
else { ... }
メソッドがVoid
を返すように宣言されている場合は、単に次のように使用します。
if object.method?(args) { ... }
見る:
「オプションチェーンによるメソッド呼び出し」
抜粋:アップル社 "The Swift Programming Language"。
iBooks https://itun.es/us/jEUH0.l
関数はSwiftのファーストクラス型なので、プロトコルで定義されているオプションの関数がnilと比較することで実装されているかどうかを確認できます。
if (someObject.someMethod != nil) {
someObject.someMethod!(someArgument)
} else {
// do something else
}
Swift 2では、AppleがAPI availability checking
という新しい機能を導入しました。これは、respondsToSelector:
メソッドの代わりになる可能性があります。以下のコードスニペットの比較は、WWDC2015のセッションからコピーされたものです。106 Swiftの新機能 あなたを助けるかもしれません、あなたがより多くを知る必要があるならば、それをチェックしてください。
古いアプローチ:
@IBOutlet var dropButton: NSButton!
override func awakeFromNib() {
if dropButton.respondsToSelector("setSpringLoaded:") {
dropButton.springLoaded = true
}
}
より良いアプローチ:
@IBOutlet var dropButton: NSButton!
override func awakeFromNib() {
if #available(OSX 10.10.3, *) {
dropButton.springLoaded = true
}
}
Swift 3.0の場合
import UIKit
@objc protocol ADelegate : NSObjectProtocol {
@objc optional func hi1()
@objc optional func hi2(message1:String, message2:String)
}
class SomeObject : NSObject {
weak var delegate:ADelegate?
func run() {
// single method
if let methodHi1 = delegate?.hi1 {
methodHi1()
} else {
print("fail h1")
}
// multiple parameters
if let methodHi2 = delegate?.hi2 {
methodHi2("superman", "batman")
} else {
print("fail h2")
}
}
}
class ViewController: UIViewController, ADelegate {
let someObject = SomeObject()
override func viewDidLoad() {
super.viewDidLoad()
someObject.delegate = self
someObject.run()
}
// MARK: ADelegate
func hi1() {
print("Hi")
}
func hi2(message1: String, message2: String) {
print("Hi \(message1) \(message2)")
}
}
あなただけのメソッドを呼び出したい場合は、以下のコードを実行します。
self.delegate?.method?()
現在(Swift 2.1)、3つの方法で確認できます。
を使用して '?' @スルタンで回答
そしてas?
演算子を使う:
if let delegateMe = self.delegate as? YourCustomViewController
{
delegateMe.onSuccess()
}
基本的にそれはあなたが達成しようとしていることによります:
swiftによる他の可能な構文.
if let delegate = self.delegate, method = delegate.somemethod{
method()
}
私はこれを自分でプロジェクトに実装するだけです。下記のコードを参照してください。 @Christopher Pickslayが述べているように、関数はファーストクラスの市民であり、したがってオプション変数のように扱うことができることを覚えておくことが重要です。
@objc protocol ContactDetailsDelegate: class {
optional func deleteContact(contact: Contact) -> NSError?
}
...
weak var delegate:ContactDetailsDelegate!
if let deleteContact = delegate.deleteContact {
deleteContact(contact)
}
古いプロジェクトをSwift 3.2にアップデートし始めたので、メソッドを次のように変更する必要がありました。
respondsToSelector(selector)
に:
responds(to: selector)
私はguard let else
を使用していますので、デリゲートfuncが実装されていない場合はデフォルトの処理を実行できます。
@objc protocol ViewController2Delegate: NSObjectProtocol {
optional func viewController2(controller: ViewController2, didSomethingWithStringAndReturnVoid string: String)
optional func viewController2(controller: ViewController2, didSomethingWithStringAndReturnString string: String) -> String
}
class ViewController2: UIViewController {
weak var delegate: ViewController2Delegate?
@IBAction func onVoidButtonClicked(sender: AnyObject){
if (delegate != nil && delegate!.respondsToSelector(Selector("viewController2:didSomethingWithStringAndReturnVoid:"))) {
NSLog("ReturnVoid is implemented")
delegate!.viewController2!(self, didSomethingWithStringAndReturnVoid: "dummy")
}
else{
NSLog("ReturnVoid is not implemented")
// Do something by default
}
}
@IBAction func onStringButtonClicked(sender: AnyObject){
guard let result = delegate?.viewController2?(self, didSomethingWithStringAndReturnString: "dummy") else {
NSLog("ReturnString is not implemented")
// Do something by default
return
}
NSLog("ReturnString is implemented with result: \(result)")
}
}