2016-07-19 17 views
4

これは単純な学問ではなく、実際のコードです。EXC_BAD_ACCESS using self.performSelector

performSelector関数を使用して印刷メソッドを実行します。しかし、このコードをプレイグラウンドで実行すると、例外がスローされます。

EXC_BAD_ACCESS(code = EXC_I386_GPFLT)。

コード:

//: Playground - noun: a place where people can play 

import UIKit 

@objc(Foo) 
class Foo: NSObject { 

    func timer() { 
     self.performSelector(#selector(Foo.print)) 
    } 

    @objc func print() { 
     NSLog("print") 
    } 
} 

let instance = Foo() 
instance.timer()  // <-- EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 

問題がありますか?私は、コードがあまりにも遊び場で実行されると信じてい

@objc func print() -> AnyObject? { 
     NSLog("print") 
     return nil 
    } 

+1

ストレンジが、それは遊び場でクラッシュそれはプロジェクトで動作します。 – Moritz

答えて

3

はこのような何かにあなたのFoo.print()を変更してみてください。

performSelector返品の種類はVoidではありません。

- performSelector:

func performSelector(_ aSelector: Selector) -> Unmanaged<AnyObject>! 

ので、遊び場は、表示する結果の値を取得しようとします。実際には返されません。

+0

私は 'performSelector'の結果を印刷していないので、' timer'の結果を 'Void'として出力しています。 – JAL

+0

@ JAL、それは遊び場が各表現をどのように扱うかではありません。あなたの仮説を支持する事実? – OOPer

+0

はい、 'NSObject'から継承しないようにクラスを変更し、' timer() 'を'(self as AnyObject).performSelector(#selector(Foo.print)) 'に変更してください。クラッシュはありません。ラインは、プレイグラウンドでは「なし」と評価されます。 – JAL

3

ここでは関数のシグネチャの変更を必要としないソリューションです:

class Foo { 

    func timer() { 
     (self as AnyObject).performSelector(#selector(Foo.print)) 
    } 

    @objc func print() { 
     NSLog("print") 
    } 
} 

let instance = Foo() 
instance.timer() 

はまだ調査し、Objective-CのAPIの橋渡しを行う必要があることがあります...