Programing

Swift는 respondsToSelector에 해당하는 것은 무엇입니까?

crosscheck 2020. 5. 14. 22:25
반응형

Swift는 respondsToSelector에 해당하는 것은 무엇입니까?


나는 구글 검색했지만 그와 동등한 것이 무엇인지 알 수 없었다 respondsToSelector:.

이것은 내가 찾을 수있는 유일한 것 ( Swift alternatives respondsToSelector :) 이지만 대리인의 존재를 확인하는 경우 내 경우에는 관련이 없습니다. 대리인이 없으며 새로운 API가 있는지 확인하고 싶습니다. 장치에서 실행 중이거나 이전 버전의 API로 폴백하지 않는 경우.


언급했듯이 Swift에서 대부분의 경우 ?선택적 unwrapper 연산자를 사용하여 필요한 것을 얻을 수 있습니다 . 이를 통해 객체가 존재하고 (아님 nil) 메소드가 구현 된 경우에만 객체에서 메소드를 호출 할 수 있습니다 .

여전히 필요한 경우 프로토콜의 respondsToSelector:일부로 여전히 존재 NSObject합니다.

respondsToSelector:Swift에서 Obj-C 유형을 호출 하는 경우 예상대로 작동합니다. 자신의 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:").


실제 Swift 교체는 없습니다.

다음과 같은 방법으로 확인할 수 있습니다.

someObject.someMethod?()

someMethod객체에 정의 된 경우에만 메소드를 호출 someObject하지만 @objc메소드를로 선언 한 프로토콜 에만 사용할 수 있습니다 optional.

Swift는 본질적으로 안전한 언어이므로 메소드를 호출 할 때마다 Swift가 메소드가 있는지 알아야합니다. 런타임 검사가 불가능합니다. 임의의 개체에 대해 임의의 메서드를 호출 할 수는 없습니다.

Obj-C에서도 ARC와 잘 작동하지 않기 때문에 가능하면 이러한 것들을 피해야합니다 (ARC는에 대해 경고를 트리거 함 performSelector:).

그러나 사용 가능한 API를 확인할 때 인스턴스를 respondsToSelector:처리하는 경우 Swift를 사용 하더라도 여전히을 사용할 수 있습니다 NSObject.

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

메소드가 returning으로 선언되면 다음을 Void사용하십시오.

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

보다:

"선택적 체인을 통한 호출 방법"
발췌 : Apple Inc. "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
    }
}

스위프트 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)")
    }
}

swift3

메소드를 호출하려면 아래 코드를 실행하십시오.

self.delegate?.method?()


현재 (Swift 2.1) 세 가지 방법으로 확인할 수 있습니다.

  1. 사용 respondsToSelector가 @Erik_at_Digit 응답
  2. 사용 '?' 의해 답변을 @Sulthan

  3. 그리고 as?연산자 사용하기 :

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

Basically it depends on what you are trying to achieve:

  • If for example your app logic need to perform some action and the delegate isn't set or the pointed delegate didn't implement the onSuccess() method (protocol method) so option 1 and 3 are the best choice, though I'd use option 3 which is Swift way.
  • If you don't want to do anything when delegate is nil or method isn't implemented then use option 2.

I just implement this myself in a project, see code below. As mentions by @Christopher Pickslay it is important to remember that functions are first class citizens and can therefore be treated like optional variables.

@objc protocol ContactDetailsDelegate: class {

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

...

weak var delegate:ContactDetailsDelegate!

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

another possible syntax by swift..

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

As I started to update my old project to Swift 3.2, I just needed to change the method from

respondsToSelector(selector)

to:

responds(to: selector)

I use guard let else, so that can do some default stuff if the delegate func is not implemented.

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

protocol

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

Object

class SomeObject : NSObject {

weak var delegate:SomeObject?

func delegateMethod() {

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

   }

}

The equivalent is the ? operator:

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

importantMethod will only be called if myQuestionableObject exists and implements it.

참고URL : https://stackoverflow.com/questions/24167791/what-is-the-swift-equivalent-of-respondstoselector

반응형