2016-03-23 14 views
9
protocol LazyUpdateable { 
    func waitToDoStuff() 
    func myMethodName() 
} 


extension LazyUpdateable where Self: NSObject { 
    func waitToDoStuff() { 
     self.performSelector(#selector(myMethodName), withObject: nil, afterDelay: 1.5) 
    } 

    func myMethodName() { 

    } 
} 

このアップデートでは、エラーArgument of #selector refers to a method that is not exposed to objective cが表示されますが、古いSelector("myMethodName")と一緒に行った場合、より良い方法に変更するよう警告が表示されます。この場合、#selector()を使用できますか?私のプロトコルで@objcを設定すると動作しません。試しました。ここでプロトコル拡張で#selector(myMethodName)を使用するにはどうすればよいですか?

あなたはそれはそれは@objc

import Foundation 
import UIKit 
import XCPlayground 


@objc protocol LazyUpdatable { 
    optional func waitToDoStuff() 
    optional func myMethodName() 
} 

extension LazyUpdatable where Self: UIViewController { 
    func waitToDoStuff() { 
     self.performSelector(#selector(myMethodName), withObject: nil, afterDelay: 1.5) 
    } 

    func myMethodName() { 
     print("LOL") 
    } 
} 


@objc 
class AViewController: UIViewController, LazyUpdatable { 
    func start() { 
     waitToDoStuff() 
    } 
} 

let aViewController = AViewController() 
aViewController.start() 

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true 

答えて

3

#selectorを使用して派遣ダイナミック()またはセレクター()あなたのスウィフトプロトコル拡張を参照してくださいしない設定では動作しません示して試すことができる遊び場です。代わりに、Objective-Cを可能な限り避けてください。

protocol LazyUpdatable { 

    func waitToDoStuff() 
    func myMethodName() 
} 

extension LazyUpdatable { 

    func waitToDoStuff() { 
     let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1.5 * Double(NSEC_PER_SEC))) 
     dispatch_after(dispatchTime, dispatch_get_main_queue()) { 
      self.myMethodName() 
     } 
    } 

    func myMethodName() { 
     print("Aloha!") 
    } 
} 

class ViewController: UIViewController, LazyUpdatable { 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     waitToDoStuff() 
    } 
} 

これは、セレクタを使用する場合ほど柔軟ではありませんが、実際のSwiftプロトコル拡張を使用できるようにします。あなたが使用することができます

var lazyUpdatableCancelKey = UInt8(0) 

protocol LazyUpdatable: class { 

    func waitToDoStuff() 
    func cancelDoingStuff() 
    func myMethodName() 
} 

extension LazyUpdatable { 

    func waitToDoStuff() { 
     let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1.5 * Double(NSEC_PER_SEC))) 
     dispatch_after(dispatchTime, dispatch_get_main_queue()) { 
      if let shouldCancel = objc_getAssociatedObject(self, &lazyUpdatableCancelKey) as? Bool where shouldCancel == true { 
       return 
      } 
      self.myMethodName() 
     } 
    } 

    func cancelDoingStuff() { 
     objc_setAssociatedObject(self, &lazyUpdatableCancelKey, true, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
    } 

    func myMethodName() { 
     print("Aloha!") 
    } 
} 

class ViewController: UIViewController, LazyUpdatable { 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     waitToDoStuff() 

     let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1.4 * Double(NSEC_PER_SEC))) 
     dispatch_after(dispatchTime, dispatch_get_main_queue()) { 
      self.cancelDoingStuff() 
     } 
    } 
} 
1

XCodeの8.2.1とスウィフト3.

ます:

EDIT: あなたはメソッド呼び出しを呼び出す取り消すことができるようにしたい場合は、以下を試してみてくださいは、あなたのような伝統的なSelector("methodName")を試してみました。すべてはあなたのプロトコル内にあるので、また、あなたはあなたが

をクラッシュしてしまうタイプミスを作ってあげるにくいですカッコ Selector(("methodName"))

でそれをラップすることにより、警告を沈黙することができます

関連する問題