Quel est L'équivalent Swift de respondsToSelector?

j'ai googlé mais je n'ai pas pu trouver ce qu'est l'équivalent swift de respondsToSelector: .

C'est la seule chose que j'ai pu trouver ( alternative Swift à respondsToSelector: ) mais ce n'est pas très pertinent dans mon cas car elle vérifie l'existence du délégué, Je n'ai pas de délégué je veux juste vérifier si une nouvelle API existe ou non en cours d'exécution sur le périphérique et si ce n'est pas retomber sur une version précédente de l'api.

174
demandé sur Honey 2014-06-11 20:16:13

16 réponses

comme mentionné, dans Swift la plupart du temps, vous pouvez obtenir ce dont vous avez besoin avec l'opérateur ? optionnel unwrapper . Cela vous permet d'appeler une méthode sur un objet si et seulement si l'objet existe (pas nil ) et que la méthode est implémentée.

dans le cas où vous avez encore besoin de respondsToSelector: , il est toujours présent dans le cadre du protocole NSObject .

Si vous appelez respondsToSelector: sur un Obj-C tapez dans Swift, puis ça fonctionne comme vous vous y attendez. Si vous l'utilisez sur votre propre classe Swift, vous devez vous assurer que votre classe dérive de NSObject .

voici un exemple de classe Swift que vous pouvez vérifier si elle répond à un sélecteur:

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

il est important de ne pas omettre les noms des paramètres. Dans cet exemple, Selector("sleep::") est et non comme Selector("sleep:minutes:") .

149
répondu Erik 2014-07-29 01:57:58

il n'y a pas de véritable remplacement Swift.

vous pouvez enregistrer de la manière suivante:

someObject.someMethod?()

ceci appelle la méthode someMethod seulement si elle est définie sur l'objet someObject mais vous pouvez l'utiliser seulement pour les protocoles @objc qui ont déclaré la méthode comme optional .

Swift est intrinsèquement une langue sûre donc chaque fois que vous appelez une méthode Swift doit savoir que la méthode est là. Pas de contrôle d'exécution est possible. Vous ne pouvez pas appeler des méthodes aléatoires sur des objets aléatoires.

Même en Obj-C, vous devriez éviter de telles choses lorsque cela est possible parce qu'il ne joue pas bien avec de l'ARC (ARC déclenche alors des avertissements pour les performSelector: ).

cependant, lors de la vérification des API disponibles, vous pouvez toujours utiliser respondsToSelector: , même si Swift, si vous avez affaire à des NSObject instances:

@interface TestA : NSObject

- (void)someMethod;

@end

@implementation TestA

//this triggers a warning

@end   



var a = TestA()

if a.respondsToSelector("someMethod") {
   a.someMethod()
}
58
répondu Sulthan 2016-02-26 20:53:10

mise à jour du 20 mars 2017 pour la syntaxe Swift 3:

si vous ne vous souciez pas si la méthode optionnelle existe, appelez simplement delegate?.optionalMethod?()

sinon, utiliser guard est probablement la meilleure approche:

weak var delegate: SomeDelegateWithOptionals?

func someMethod() {
    guard let method = delegate?.optionalMethod else {
        // optional not implemented
        alternativeMethod()
        return
    }
    method()
}

réponse originale:

, Vous pouvez utiliser le "laissé" approche pour tester un protocole facultatif comme ceci:

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()
}
32
répondu hyouuu 2017-03-21 00:12:12

il semble que vous ayez besoin de définir votre protocole comme un sous-protocole de NSObjectProtocol ... vous obtiendrez alors la méthode respondsToSelector

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

notez qu'il ne suffit pas de spécifier @objc. Vous devez également veiller à ce que le délégué réel soit une sous - classe de NSObject-ce qui n'est peut-être pas le cas dans Swift.

11
répondu Matej Ukmar 2014-10-20 16:43:19

si la méthode que vous testez est définie comme une méthode optionnelle dans un @objc protocole (qui ressemble à votre cas), puis utiliser le chaîne optionnelle motif comme:

if let result = object.method?(args) {
  /* method exists, result assigned, use result */
}
else { ... }

lorsque la méthode est déclarée comme retournant Void , il suffit d'utiliser:

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

voir:

" Méthodes D'Appel Optionnelles Chaînage "

Extrait De: Apple Inc. "Le Langage De Programmation Swift."

iBooks. https://itun.es/us/jEUH0.l

10
répondu GoZoner 2015-04-07 19:44:03

les fonctions sont de premier ordre dans Swift, vous pouvez donc vérifier si une fonction optionnelle définie dans un protocole a été implémentée en la comparant à nil:

if (someObject.someMethod != nil) {
    someObject.someMethod!(someArgument)
} else {
    // do something else
}
9
répondu Christopher Pickslay 2015-01-21 22:50:01

dans Swift 2,Apple a introduit une nouvelle fonctionnalité appelée API availability checking , qui pourrait remplacer la méthode respondsToSelector: .La comparaison d'extraits de code suivante est copiée de la session 106 de la WWDC2015 Quoi de neuf dans Swift qui pourrait vous aider,s'il vous plaît vérifiez si vous avez besoin d'en savoir plus.

L'Ancienne Approche:

@IBOutlet var dropButton: NSButton!
override func awakeFromNib() {
    if dropButton.respondsToSelector("setSpringLoaded:") {
        dropButton.springLoaded = true
    }
}

La Meilleure Approche:

@IBOutlet var dropButton: NSButton!
override func awakeFromNib() {
    if #available(OSX 10.10.3, *) {
        dropButton.springLoaded = true
    }
}
7
répondu tounaobun 2015-06-13 13:41:18

pour swift3

si vous voulez simplement appeler la méthode, lancez le code ci-dessous.

self.delegate?.method?()

5
répondu Jason Yu 2017-08-23 07:36:20

actuellement (Swift 2.1), vous pouvez le vérifier en utilisant 3 méthodes:

  1. en utilisant repondstoselector answered by @Erik_at_Digit
  2. par "?' , a répondu par @Sulthan

  3. et en utilisant as? opérateur:

    if let delegateMe = self.delegate as? YourCustomViewController
    {
       delegateMe.onSuccess()
    }
    

fondamentalement, cela dépend de ce que vous essayez d'atteindre:

  • si par exemple votre logique app doit effectuer une action et que le délégué n'est pas défini ou que le délégué pointé n'a pas implémenté la méthode onSuccess () (méthode de protocole) donc les options 1 et 3 sont le meilleur choix, bien que j'utilise l'option 3 qui est Swift way.
  • si vous ne voulez rien faire lorsque délégué est nul ou que la méthode n'est pas implémentée, utilisez l'option 2.
4
répondu OhadM 2017-05-23 10:31:37

pour 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)")
    }
}
4
répondu Kakashi 2017-06-07 16:55:18

je viens de mettre en œuvre moi-même dans un projet, voir code ci-dessous. Comme le mentionne @Christopher Pickslay, il est important de se rappeler que les fonctions sont des citoyens de première classe et peuvent donc être traitées comme des variables optionnelles.

@objc protocol ContactDetailsDelegate: class {

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

...

weak var delegate:ContactDetailsDelegate!

if let deleteContact = delegate.deleteContact {
    deleteContact(contact)
}
2
répondu Bulwinkel 2015-05-23 14:43:59

une autre syntaxe possible de swift..

 if let delegate = self.delegate, method = delegate.somemethod{
        method()
    }
2
répondu Janub 2016-03-01 12:50:33

alors que j'ai commencé à mettre à jour mon ancien projet vers Swift 3.2, j'ai juste eu besoin de changer la méthode de

respondsToSelector(selector)

à:

responds(to: selector)
1
répondu chAlexey 2018-05-08 10:05:28

j'utilise guard let else , donc cela peut faire quelques trucs par défaut si la func déléguée n'est pas implémentée.

@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)")
    }
}
0
répondu dichen 2016-03-25 22:46:21

Swift 3:

protocole

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

objet

class SomeObject : NSObject {

weak var delegate:SomeObject?

func delegateMethod() {

     if let delegateMethod = delegate?.method{
         delegateMethod()
     }else {
        //Failed
     }

   }

}
-1
répondu etzuk 2017-02-05 09:11:04

l'équivalent est le ? exploitant:

var value: NSNumber? = myQuestionableObject?.importantMethod()

méthode importante ne sera appelée que si myquestionabject existe et l'implémente.

-4
répondu Ben Gottlieb 2014-06-11 16:24:13