2016-10-02 2 views
3

Я пишу свой IOS приложение в Swift 3.Использование селектора в Swift 3

У меня есть UIViewController расширение, где я должен проверить, если экземпляр контроллера отвечает методу. Ниже приведен код, который я тестирую.

extension UIViewController { 
func myMethod() { 
    if self.responds(to: #selector(someMethod)) { 

    } 
}} 

Здесь метод responds(to:) бросает компиляции ошибки времени

Use of unresolved identifier "someMethod".

Я прочитал в другом посте, мы должны использовать self внутри аргумента селектор, но даже то, что бросает ошибку.

+0

Вы должны реализовать 'Func SomeMethod() {}', что делает метод 'откликается (для:' бесполезен – vadian

+0

@vadian Он реализован в одном из экземпляров View Controller .. Но все контроллеры представлений могут и не быть, и это то, что я намерен проверить. – Adithya

+0

Я считаю, что вы хотите использовать протокол с дополнительными (или даже не факультативными) методами, а не просто проверять случайные объекты для метода. – Sulthan

ответ

4

Простое решение:

@objc protocol SomeMethodType { 
    func someMethod() 
} 
extension UIViewController { 
    func myMethod() { 
     if self.responds(to: #selector(SomeMethodType.someMethod)) { 
      //... 
      self.perform(#selector(SomeMethodType.someMethod)) 
      // or 
      (self as AnyObject).someMethod?() 
      //... 
     } 
    } 
} 

Побольше Swifty путь:

protocol SomeMethodType { 
    func someMethod() 
} 
//For all classes implementing `someMethod()`. 
extension MyViewController: SomeMethodType {} 
//... 
extension UIViewController { 
    func myMethod() { 
     if let someMethodSelf = self as? SomeMethodType { 
      //... 
      someMethodSelf.someMethod() 
      //... 
     } 
    } 
} 
+0

Удивительный! Кажется, это путь. Благодаря! – Adithya

+1

Почему у вас есть 2 расширения? – Honey

+0

Мое толкование: ** 1. ** Определяет новый протокол. ** 2. ** Расширяет определенный подкласс UIViewController, чтобы быть разработчиком этого протокола. ** 3.** Расширяет суперкласс, чтобы проверить, реализует ли какой-либо экземпляр (даже если он подклассифицирован), и если это так, вызывает метод, требуемый протоколом, в предположении, что если протокол определен, метод присутствует (поскольку протокол требует его). *** Наконец ***: Причина, по которой второе расширение существует, не является разумным и почти наверняка не может требовать * каждого * UIViewController для реализации протокола. – clearlight

4

Создать протокол, который требует someMethod()

protocol Respondable { 
    func someMethod() 
} 

И расширение протокола, который затрагивает только UIViewController экземпляры

extension Respondable where Self : UIViewController { 

    func myMethod() { 
    someMethod() 
    } 
} 

Принять протокол к некоторым контроллерам зрения

class VC1 : UIViewController, Respondable { 
    func someMethod() { print("Hello") } 
} 

class VC2 : UIViewController {} 
class VC3 : UIViewController {} 

сейчас вызов метода в расширении

let vc1 = VC1() 
vc1.myMethod() // "Hello" 

В противном случае вы получите ошибку компиляции:

let vc3 = VC3() 
vc3.myMethod() // error: value of type 'VC3' has no member 'myMethod' 
+0

Спасибо за ответ, но я не уверен, подходит ли этот метод для моего прецедента. как только я подтвержу. – Adithya

+1

Преимущество протокола заключается в том, что «проверка» выполняется в ** время компиляции **. – vadian

0

Swift 4 ответ:

Если селектор записан как строка, вы не получите эту ошибку.

extension UIViewController { 
    func myMethod() { 
     if self.responds(to: "someMethod")) { 

     } 
    } 
} 

А потом в ViewController (не забывайте о @objc):

@objc func someMethod() -> Void {} 
Смежные вопросы