2016-02-17 4 views
1

У меня есть код, как это:Быстрое селектор для функции протокола?

protocol FooP { 
    ... 
} 

extension FooP { 
    func doFoo() { 
     print("foo") 
    } 
    func doFoo(timer: NSTimer) { 
     doFoo() 
    } 
} 
class A : NSObject, UITableViewDataSource, FooP { 
    var timer : NSTimer? 

    ... 

    func startUpdating() { 
     timer = NSTimer.scheduledTimerWithTimeInterval(
     1.0, 
     target: self, 
     selector: Selector("doFoo:"), 
     userInfo: nil, 
     repeats: true 
    ) 
    } 
} 

К сожалению, он выходит из строя, когда я начинаю таймер аварий программ с

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[xyz.A doFoo:]: unrecognized selector sent to instance 0x7fb2041c4ac0' 

Как я могу заставить его работать (я хочу сохранить реализацию doFoo внутри протокола) ?

Если я переведу doFoo в определение класса, все работает нормально, но, как я уже сказал, я хочу реализовать эту функцию внутри протокола.

Другими словами, мне нужно селектор, который говорит

"Hey I point to function named "doFoo" that is implemented as extension to FooP" 

Сейчас селектор кажется сказать

"Hey I point to function named "doFoo" that is implemented in A class" 
+0

Возможный дубликат ["Непризнанный селектор, посланный экземпляру" в быстром режиме) (http://stackoverflow.com/questions/24094620/unrecognized-selector-sent-to-instance-in-swift) – Matheno

+0

Нет, моя проблема в том, что таймер не видит функций, реализованных в качестве расширений для протокола – Pikacz

+0

У меня была та же проблема. у вас есть решение? Я просто реализую funciton в своем классе на данный момент –

ответ

1

Попробуйте сыграть в вашей площадке. Ваша проблема в том, что нет возможности определять функцию @objc в расширении протокола. Итак, см. Возможное обходное решение

import XCPlayground 
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true 
import Foundation 

protocol FooP { 
} 

extension FooP { 
    func doFoo() { 
     print("foo") 
    } 
    func doFoo(timer: NSTimer) { 
     print("dofoo") 
     doFoo() 
    } 
} 
class A: FooP { 
    var timer : NSTimer? 
    @objc func foo(timer: NSTimer) { 
     doFoo(timer) 
    } 
    func startUpdating() { 
     timer = NSTimer.scheduledTimerWithTimeInterval(
      1.0, 
      target: self, 
      selector: "foo:", 
      userInfo: nil, 
      repeats: true 
     ) 
    } 
} 

let a = A() 
a.startUpdating() 

Почему это работает для вас, если вы перемещаете doFoo внутри класса A? Это потому, что ваш класс наследуется от NSObject, поэтому ключевое слово @objc не требуется.

1

Проблема в том, что NSTimer и весь бизнес Selector() - это объекты Objective-C и работают в области Swift благодаря мостику. Тем не менее, реализация протокола по умолчанию Swift - , а не, соединенная с Objective-C wonderland (пока), и поэтому ваш таймер выходит из строя. В принципе, из объективов Objective-C типа A do не отвечать на селектор doFoo:, период.

Итак, сообщите об этом прецеденте для быстрой эволюции для долгосрочного решения. Краткосрочный, используйте какое-то обходное решение.

Кстати, вам может показаться интересным прочитать (или даже принять участие) в этом thread.

Смежные вопросы