Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c Swift与respondsToSelector的等价物是什么?_Objective C_Swift_Selector - Fatal编程技术网

Objective c Swift与respondsToSelector的等价物是什么?

Objective c Swift与respondsToSelector的等价物是什么?,objective-c,swift,selector,Objective C,Swift,Selector,我在谷歌上搜索过,但没能找到swift与响应选择器:的等价物 这是我能找到的唯一一件事(),但在我的情况下并不太相关,因为它检查委托的存在,我没有委托,我只是想检查在设备上运行时是否存在新的API,如果没有,则返回到以前版本的API。没有真正的快速替换 您可以通过以下方式进行检查: someObject.someMethod?() 只有在对象someObject上定义了方法someMethod时,才会调用方法someMethod,但您只能将其用于声明方法为可选的@objc协议 Swift本质上

我在谷歌上搜索过,但没能找到swift与响应选择器:的等价物


这是我能找到的唯一一件事(),但在我的情况下并不太相关,因为它检查委托的存在,我没有委托,我只是想检查在设备上运行时是否存在新的API,如果没有,则返回到以前版本的API。

没有真正的快速替换

您可以通过以下方式进行检查:

someObject.someMethod?()
只有在对象
someObject
上定义了方法
someMethod
时,才会调用方法
someMethod
,但您只能将其用于声明方法为
可选的
@objc
协议

Swift本质上是一种安全的语言,因此每次调用方法时,Swift都必须知道该方法存在。不可能进行运行时检查。你不能只对随机对象调用随机方法

即使在Obj-C中,您也应该尽可能避免这些事情,因为它不能很好地使用ARC(ARC随后会触发
性能选择器的警告:

但是,在检查可用的API时,如果您处理的是
NSObject
实例,则即使使用Swift,您仍然可以使用
respondsToSelector:

@interface TestA : NSObject

- (void)someMethod;

@end

@implementation TestA

//this triggers a warning

@end   


等价物是?接线员:

var value: NSNumber? = myQuestionableObject?.importantMethod()
if let delegateMe = self.delegate as? YourCustomViewController
{
   delegateMe.onSuccess()
}

仅当MyQuestibleObject存在并实现它时,才会调用importantMethod。

如前所述,在Swift中,大多数情况下,您可以使用
可选的展开器操作符来实现所需。这允许您在且仅当对象存在(而不是
nil
)且方法已实现时,对对象调用方法

@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)")
    }
}
如果仍然需要
响应选择器:
,它仍然作为
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:”)
Selector(“sleep:minutes:”)
不同,如果您测试的方法被定义为@objc协议中的可选方法(听起来像您的案例),则使用可选的链接模式如下:

if let result = object.method?(args) {
  /* method exists, result assigned, use result */
}
else { ... }
当该方法声明为返回
Void
时,只需使用:

if object.method?(args) { ... }
见:

“通过可选链接调用方法”
摘自:苹果公司的《Swift编程语言》。
我的书


似乎您需要将您的协议定义为NSObjectProtocol的子协议。。。然后您将得到respondsToSelector方法

@objc protocol YourDelegate : NSObjectProtocol
{
    func yourDelegateMethod(passObject: SomeObject)
}

请注意,仅指定@objc是不够的。您还应注意,实际委托是NSObject的一个子类,而在Swift中可能不是。

更新2017年3月20日的Swift 3语法:

如果您不关心可选方法是否存在,只需调用
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()
}

函数是Swift中的一级类型,因此您可以通过将协议中定义的可选函数与nil进行比较来检查该函数是否已实现:

if (someObject.someMethod != nil) {
    someObject.someMethod!(someArgument)
} else {
    // do something else
}

我只是在一个项目中自己实现这个,请参见下面的代码。正如@Christopher Pickslay所提到的,重要的是要记住函数是一级公民,因此可以被视为可选变量

@objc protocol ContactDetailsDelegate: class {

    optional func deleteContact(contact: Contact) -> NSError?
}

...

weak var delegate:ContactDetailsDelegate!

if let deleteContact = delegate.deleteContact {
    deleteContact(contact)
}

在Swift 2中,苹果公司推出了一项新功能,名为
API可用性检查
,它可能会取代
respondsToSelector:
方法。下面的代码片段比较是从WWDC2015会话106复制的,我认为这可能会对您有所帮助,如果您需要了解更多信息,请查看

旧方法:

更好的方法是:


swift提供的另一种可能的语法

 if let delegate = self.delegate, method = delegate.somemethod{
        method()
    }
目前(Swift 2.1),您可以使用3种方式进行检查:

  • 使用@Erik_在数字处回答
  • 使用@Sulthan的回答

  • 并使用
    作为
    运算符:

    var value: NSNumber? = myQuestionableObject?.importantMethod()
    
    if let delegateMe = self.delegate as? YourCustomViewController
    {
       delegateMe.onSuccess()
    }
    
  • 基本上,这取决于您试图实现的目标:

    • 例如,如果您的应用程序逻辑需要执行某些操作,而委托没有设置,或者指定的委托没有实现onSuccess()方法(协议方法),那么选项1和3是最佳选择,尽管我会使用选项3,这是一种快速的方法
    • 当委托为nil或方法未实现时,如果您不想执行任何操作,请使用选项2

    我使用了
    guard let else
    ,这样,如果没有实现委托函数,就可以执行一些默认操作

    @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)")
        }
    }
    
    适用于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)")
        }
    }
    
    Swift 3:

    协议

    @objc protocol SomeDelegate {
        @objc optional func method()
    }
    
    反对

    class SomeObject : NSObject {
    
    weak var delegate:SomeObject?
    
    func delegateMethod() {
    
         if let delegateMethod = delegate?.method{
             delegateMethod()
         }else {
            //Failed
         }
    
       }
    
    }
    
    对于swift3 如果您只想调用该方法,请运行下面的代码


    self.delegate?.method?()

    当我开始将我的旧项目更新为Swift 3.2时,我只需要将方法从

    respondsToSelector(selector)
    
    致:


    我想您应该为委托创建一个默认实现。您可以这样做:

    let defaultHandler = {}
    (delegate?.method ?? defaultHandler)()
    

    所有这些都意味着用可选的替换,并用可选的链接来执行。鉴于苹果明确建议使用
    NSClassFromString
    respondsToSelector
    等机制来检查新实现的功能,我不得不相信这些机制要么已经到位,或者在释放前会在那里。尝试观看WWDC的
    高级互操作…
    视频。@Jack Wu但如果新方法是在UIApplication或UIViewController等基础上引入的新方法,该怎么办。这些目标
    let defaultHandler = {}
    (delegate?.method ?? defaultHandler)()