उत्तर स्विफ्टटाइलेक्टर के स्विफ्ट के बराबर क्या है?


195

मैंने गुगली की है, लेकिन यह पता नहीं लगा पाया है कि यह स्विफ्ट किसके बराबर है respondsToSelector: है।

यह केवल एक चीज है जो मैं पा सकता हूं ( स्विफ्ट विकल्प का उत्तर दें या नहीं जब डिवाइस पर चल रहा है और यदि नहीं तो आप एपीआई के पिछले संस्करण में वापस आ सकते हैं।


इन सभी को वैकल्पिक के साथ प्रतिस्थापित किया जाना है, और वैकल्पिक चेनिंग के साथ अभ्यास किया जाता है
जैक

यह देखते हुए कि एप्पल स्पष्ट रूप से उपयोग करने की सलाह NSClassFromStringऔर respondsToSelectorनव कार्यान्वित कार्यक्षमता के लिए जाँच के लिए अन्य यांत्रिकी के बीच में, मुझे विश्वास है कि तंत्र या तो पहले से ही जगह में हैं, या रिलीज होने से पहले नहीं होगा मिल गया है। Advanced Interop...WWDC से वीडियो देखने की कोशिश करें ।
डेविड बेरी

2
@ जैक वू लेकिन क्या होगा अगर नई विधि कुछ नया है जिसे UIApplication या UIViewController जैसे कुछ मौलिक पर पेश किया गया है। ये ऑब्जेक्ट वैकल्पिक नहीं हैं और नई विधि वैकल्पिक नहीं है। यदि आप उदाहरण के लिए कॉल करना चाहते हैं तो आप कैसे चेक कर सकते हैं UIApplcation: newVersionOfMethodX या आपको UIApplication को कॉल करना होगा: deprecatedVersionOfMethodX? (यह देखते हुए कि आप iOS 7 पर स्विफ्ट में एक ऐप बना सकते हैं और चला सकते हैं, यह एक बहुत ही सामान्य परिदृश्य है)
Gruntcakes

क्या जो API आप हैं / वह Apple API से संबंधित थे?
गोजोनर

@PotassiumPermanganate - निश्चित रूप से, यदि उत्तर 'हाँ, मैं Apple APIs का उपयोग कर रहा था' तो शायद वह if #available(...)स्विफ्ट 2.x respondsToSelectorमें पहले स्थान पर उपयोग करने से बच सकता है। लेकिन आप जानते थे कि ( Apple.co/1SNGtMQ )
GoZoner

जवाबों:


170

जैसा कि उल्लेख किया गया है, स्विफ्ट के अधिकांश समय आप प्राप्त कर सकते हैं जो आपको ?वैकल्पिक अल्टरनेटर ऑपरेटर के साथ चाहिए । यह आपको ऑब्जेक्ट पर एक विधि को कॉल करने की अनुमति देता है यदि और केवल तभी ऑब्जेक्ट मौजूद है (नहीं nil) और विधि लागू की गई है।

उस मामले में जहां आपको अभी भी जरूरत है respondsToSelector:, यह अभी भी उसी के हिस्से के रूप में हैNSObject प्रोटोकॉल के है।

यदि आप respondsToSelector:स्विफ्ट में ओब्ज-सी प्रकार पर कॉल कर रहे हैं , तो यह उसी तरह काम करता है जैसा आप अपेक्षा करते हैं। यदि आप इसे अपने स्वयं के स्विफ्ट वर्ग पर उपयोग कर रहे हैं, तो आपको यह सुनिश्चित करने की आवश्यकता होगी कि आपकी कक्षा व्युत्पन्न हो NSObject

यहां एक स्विफ्ट क्लास का एक उदाहरण है जिसे आप जांच सकते हैं कि क्या वह चयनकर्ता को जवाब देता है:

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:")


मैं यह निर्धारित करने की कोशिश कर रहा हूं कि क्या iOS8 से UIApplication में पेश किया गया एक नया तरीका मौजूद है और अब तक कोई भाग्य नहीं है। यहां बताया गया है कि मैं ऊपर के अनुसार कैसे प्रयास कर रहा हूं: यदि वर्तमान = UIApplication.saredApplication ()। RespondsToSelector (चयनकर्ता ("redactedAsStillUnderNDA"))। हालाँकि, मुझे एक संकलन त्रुटि मिलती है: "सशर्त बंधन में बाध्य मूल्य वैकल्पिक प्रकार का होना चाहिए"।
ग्रंटककेस

4
आपको उन पंक्तियों को विभाजित करने याlet x = भाग को निकालने की आवश्यकता होगी । मूल रूप से, if let x = yसंरचना वैकल्पिक मानों (जैसे !) को खोलना है । चूंकि आप Boolसे वापस आ रहे हैं respondsToSelector, कंपाइलर शिकायत कर रहा है कि परिणाम एक वैकल्पिक प्रकार ( Bool?) नहीं है।
एरिक

क्या varघोषित किया जाएगा? क्या वे अभी भी उसी तरह से जवाब देते हैं? उद्देश्य-सी में मैं if ( [obj respondsToSelector:@selector(setSomeVar:)] ) { ... }एक someVarसंपत्ति के लिए कर सकता था । क्या यह varस्विफ्ट में s के साथ उसी तरह काम करता है ?
एलेजांद्रो इवान

क्या होगा यदि व्यू कंट्रोलर इंस्टेंस वैकल्पिक नहीं है, लेकिन उस कंट्रोलर में मेथड या फंक्शन लागू नहीं होता है? मुझे लगता है कि आपको यह जांचने की आवश्यकता होगी कि ऑब्जेक्ट चयनकर्ता को जवाब देता है या नहीं।
आशीष पाइसे

मैं हो रही है "प्रकार के मान 'UIViewController' कोई सदस्य 'respondsToSelector' है"
मीकल Ziobro

59

कोई वास्तविक स्विफ्ट प्रतिस्थापन नहीं है।

आप निम्न तरीके से जांच कर सकते हैं:

someObject.someMethod?()

यह विधि को someMethodकेवल तभी कॉल करता है जब इसे ऑब्जेक्ट पर परिभाषित किया जाता है, someObjectलेकिन आप इसे केवल उन @objcप्रोटोकॉल के लिए उपयोग कर सकते हैं जिन्होंने इस पद्धति को घोषित किया है optional

स्विफ्ट स्वाभाविक रूप से एक सुरक्षित भाषा है इसलिए हर बार जब आप किसी विधि को कॉल करते हैं, तो स्विफ्ट को पता होना चाहिए कि विधि क्या है। कोई रनटाइम जाँच संभव नहीं है। आप यादृच्छिक वस्तुओं पर यादृच्छिक तरीकों को नहीं कह सकते।

ओब्ज-सी में भी आपको जब संभव हो तो ऐसी चीजों से बचना चाहिए क्योंकि यह एआरसी (एआरसी) के साथ अच्छा नहीं खेलती है और इसके लिए चेतावनी जारी करती है performSelector: ) के ।

हालाँकि, उपलब्ध एपीआई की जाँच करते समय, आप तब भी उपयोग कर सकते हैं respondsToSelector:, भले ही स्विफ्ट, यदि आप NSObjectउदाहरणों के साथ काम कर रहे हैं :

@interface TestA : NSObject

- (void)someMethod;

@end

@implementation TestA

//this triggers a warning

@end   


var a = TestA()

if a.respondsToSelector("someMethod") {
   a.someMethod()
}

1
इसलिए अब ऐप्स को स्पष्ट रूप से जानना होगा कि वे किस ओएस पर चल रहे हैं? मैं एक ऐसी विधि को कॉल करना चाहता हूं जो केवल iOS8 में मौजूद है और अगर वहां नहीं है तो पुराने iOS7 संस्करण का उपयोग करें। इसलिए नई पद्धति की उपस्थिति / अनुपस्थिति की जांच करने के बजाय मुझे यह पता लगाना होगा कि मैं iOS8 पर हूं या नहीं? स्विफ्ट अच्छा है लेकिन यह थोड़ा क्लिंकी लगता है।
ग्रंटककेस

@ सुल्तान मुझे यकीन नहीं है कि आप यह कहते हुए आ रहे हैं कि आपको respondsToSelector:एप्पल की सिफारिश के रूप में उपयोग नहीं करना चाहिए, यह स्पष्ट रूप से है कि आपको ऐसा करना चाहिए। यहां
डेविड बेरी

@ डेविड, आपने कुछ मामलों में से एक पाया है जब respondsToSelector:वास्तव में अच्छा है। लेकिन अगर आप स्विफ्ट संदर्भ से गुजरते हैं, तो वे विभिन्न सिस्टम संस्करणों के लिए उपवर्गों का उपयोग करने के बारे में बोलते हैं।
सुल्तान

यदि ओपी के बारे में बात नहीं हो रही है, और वे वैकल्पिक प्रोटोकॉल मामले के बारे में बात कर रहे हैं, तो वे वैकल्पिक रूप से वैकल्पिक चेनिंग का उपयोग करने की अनुमति देते हैं (जैसा कि आपने बताया है)। किसी भी तरह से, "आपको ऐसा करने से बचना चाहिए जो Apple ने आपको स्पष्ट रूप से करने के लिए कहा है" बुरी सलाह की तरह लगता है। Apple ने "हमेशा" रन-टाइम पर वैकल्पिक कार्यक्षमता को निर्धारित करने और अभ्यास करने के लिए तंत्र प्रदान किया है।
डेविड बेरी

1
@ स्विफ्ट में हम आम तौर पर इसके बजाय उपलब्धता निर्देशों का उपयोग करते हैं, उदाहरण के लिए if #available(iOS 10) {और फिर सीधे विधि को कॉल करते हैं।
सुल्तान

40

अद्यतन मार्च 20, 2017 स्विफ्ट 3 वाक्य रचना के लिए:

यदि आपको परवाह नहीं है कि क्या वैकल्पिक विधि मौजूद है, बस कॉल करें delegate?.optionalMethod?()

अन्यथा, उपयोग guardकरना संभवतः सबसे अच्छा तरीका है:

weak var delegate: SomeDelegateWithOptionals?

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

मूल उत्तर:

आप इस तरह से एक वैकल्पिक प्रोटोकॉल का परीक्षण करने के लिए "अगर चलो" दृष्टिकोण का उपयोग कर सकते हैं:

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()
}

4
अगर देना theMethod = प्रतिनिधि .theOptionalProtocolMethod?
john07

1
कई उम्मीदवारों के चयनकर्ता वाक्यविन्यास का उदाहरण:let theMethod = delegate.userNotificationCenter(_:willPresent:withCompletionHandler:)
C

11

ऐसा लगता है कि आपको अपने प्रोटोकॉल को NSObjectProtocol के उपप्रोकोल के रूप में परिभाषित करने की आवश्यकता है ... तो आपको प्रतिक्रिया मिलेगी।

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

ध्यान दें कि केवल @objc को निर्दिष्ट करना पर्याप्त नहीं था। आपको यह भी ध्यान रखना चाहिए कि वास्तविक प्रतिनिधि NSObject का उपवर्ग है - जो स्विफ्ट में नहीं हो सकता है।


10

यदि जिस विधि के लिए आप परीक्षण कर रहे हैं, वह @objc प्रोटोकॉल में एक वैकल्पिक विधि के रूप में परिभाषित की गई है (जो कि आपके मामले की तरह लगती है), तो इस प्रकार वैकल्पिक चैनिंग पैटर्न का उपयोग करें :

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

जब विधि वापसी के रूप में घोषित की जाती है Void, तो बस उपयोग करें:

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

देख:

"वैकल्पिक श्रृंखलन के माध्यम से कॉलिंग तरीके"
अंश से: Apple Inc. "स्विफ्ट प्रोग्रामिंग लैंग्वेज।"
iBooks। https://itun.es/us/jEUH0.l


यह तभी काम करेगा जब विधि कुछ लौटाएगी, यदि यह शून्य विधि है तो क्या होगा?
ग्रंटककेस

1
यदि शून्य का उपयोग सरलता से किया जाता है if object.method?(args) { ... }- विधि की कॉल, जब यह मौजूद है, तो वह वापस आ जाएगी Voidजो कि नहीं हैnil
GoZoner

1
हालाँकि, "टाइप
वोड

कृपया संदर्भित दस्तावेज देखें (पेज 311-312)।
गोयनर

"यदि आप जिस विधि के लिए परीक्षण कर रहे हैं वह @objc प्रोटोकॉल में एक वैकल्पिक विधि के रूप में परिभाषित किया गया है" या यदि objectप्रकार है AnyObject, तो आप किसी भी @objc विधि का परीक्षण कर सकते हैं।
नवांश

9

स्विफ्ट में फ़ंक्शंस प्रथम श्रेणी के प्रकार हैं, इसलिए आप जांच सकते हैं कि प्रोटोकॉल में परिभाषित वैकल्पिक फ़ंक्शन को शून्य से तुलना करके लागू किया गया है या नहीं:

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

1
क्या होगा अगर विधि अतिभारित है? हम एक विशिष्ट के लिए कैसे जांच कर सकते हैं?
नूनो गोनाक्लेव्स

8

स्विफ्ट 3 के लिए

यदि आप केवल विधि को कॉल करना चाहते हैं, तो नीचे दिए गए कोड को चलाएं।

self.delegate?.method?()


7

स्विफ्ट 2 में, Apple ने एक नया फीचर पेश किया API availability checking, जो respondsToSelector:विधि के लिए एक प्रतिस्थापन हो सकता है। निम्नलिखित कोड स्निपेट की तुलना WWDC2015 सत्र 106 से की गई है, स्विफ्ट में नया क्या है जो मैंने सोचा था कि आपकी मदद कर सकता है, कृपया इसे जांचें अगर आपको इसकी आवश्यकता है अधिक जानिए।

पुराना दृष्टिकोण:

@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
    }
}

मुझे लगता है कि respondsToSelectorस्विफ्ट में दृष्टिकोण का उपयोग करने से कहीं बेहतर समाधान है । ऐसा इसलिए भी है क्योंकि चयनकर्ता जाँच इस समस्या (उपलब्धता जाँच) का सबसे अच्छा समाधान नहीं था।
JanApotheker

6

स्विफ्ट 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

वर्तमान में (स्विफ्ट 2.1) आप 3 तरीकों का उपयोग करके इसे देख सकते हैं:

  1. का उपयोग करते हुए respondsToSelector @Erik_at_Digit द्वारा उत्तर दिया
  2. ' का उपयोग कर ?' @Sulthan द्वारा उत्तर दिया गया

  3. और as?ऑपरेटर का उपयोग करना:

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

मूल रूप से यह इस बात पर निर्भर करता है कि आप क्या हासिल करना चाहते हैं:

  • यदि उदाहरण के लिए आपके ऐप लॉजिक को कुछ कार्रवाई करने की आवश्यकता है और प्रतिनिधि सेट नहीं है या इंगित प्रतिनिधि ने ऑनस्क्यू () विधि (प्रोटोकॉल विधि) को लागू नहीं किया है तो विकल्प 1 और 3 सबसे अच्छा विकल्प हैं, हालांकि मैं उपयोग करूंगा। विकल्प 3 जो स्विफ्ट रास्ता है।
  • यदि आप कुछ नहीं करना चाहते हैं जब प्रतिनिधि शून्य है या विधि लागू नहीं है तो विकल्प 2 का उपयोग करें।

2

मैं सिर्फ एक परियोजना में खुद को लागू करता हूं, नीचे कोड देखें। जैसा कि @Christopher Pickslay द्वारा उल्लेख किया गया है कि यह याद रखना महत्वपूर्ण है कि फ़ंक्शन प्रथम श्रेणी के नागरिक हैं और इसलिए उन्हें वैकल्पिक चर की तरह माना जा सकता है।

@objc protocol ContactDetailsDelegate: class {

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

...

weak var delegate:ContactDetailsDelegate!

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

क्या होगा अगर विधि अतिभारित है? कोई ऐसा कैसे करेगा?
नूनो गोनाक्लेव्स

2

तेजी से एक और संभावित वाक्यविन्यास ।।

 if let delegate = self.delegate, method = delegate.somemethod{
        method()
    }

2

जैसा कि मैंने अपनी पुरानी परियोजना को स्विफ्ट 3.2 में अपडेट करना शुरू कर दिया है, मुझे बस विधि को बदलने की आवश्यकता है

respondsToSelector(selector)

सेवा:

responds(to: selector)

0

मैं उपयोग करता हूं 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)")
    }
}

-1

स्विफ्ट 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
     }

   }

}

-4

समतुल्य है? ऑपरेटर:

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

महत्वपूर्णमेथोड केवल तभी कहा जाएगा जब myQuestionableObject मौजूद है और इसे लागू करता है।


लेकिन क्या होगा अगर myQuestionalObject UIApplication की तरह कुछ है (जो इसलिए अस्तित्व में है और इस प्रकार इसके अस्तित्व की जाँच करना व्यर्थ है) और importandMethod () iOS N में पेश किया गया एक नया तरीका है और आप यह निर्धारित करना चाहते हैं कि आप इसे कॉल कर सकते हैं या कॉल करना है। iOS N-1 पर पुराना deprecatedImportantMethod ()?
ग्रंटकैक्स

2
तुम भी एक के ?बाद की जरूरत हैimportantMethod
newacct
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.