2010-06-09 11 views
19

Ich habe eine iPhone App, die hauptsächlich auf 3.0 ausgerichtet ist, aber die neueren APIs nutzt, wenn sie verfügbar sind. Code geht in etwa so:Schwache Verbindung auf dem iPhone weigert sich zu arbeiten

if (UIApplicationDidEnterBackgroundNotification != NULL) { 
    [nc 
     addObserver: self 
     selector: @selector(irrelevantCallbackName:) 
     name:  UIApplicationDidEnterBackgroundNotification 
     object:  nil]; 
} 

nun nach allem Apples jemals gesagt, wenn die entsprechenden APIs schwach verknüpft sind, dass feine funktionieren wird, weil der dynamische Linker UIApplicationDidEnterBackgroundNotification-NULL bewerten wird. Außer, dass es nicht so ist. Die Anwendung kompiliert, aber sobald sie if (UIApplicationDidEnterBackgroundNotification != NULL) erreicht, stürzt sie mit EXC_BAD_ACCESS ab.

Ist das einfach eine Frage eines Compiler-Flags, das ich setzen muss? Oder mache ich das falsch?

+0

Ich * wusste * Ich würde die Antwort finden, indem Sie einfach nach UIApplicationWillEnterForegroundNotification auf SO suchen ... Es muss der häufigste Grund für Entwickler sein, mit bedingt verfügbaren globalen umzugehen. –

+0

@Pierre Lebeaupin: Das scheint der Fall zu sein. –

Antwort

38

Aaand ich fand es heraus. Für Symbole, die keine Funktionen (extern const int foobar, zum Beispiel) sind, müssen Sie gegen die Adresse des Symbols vergleichen, nicht das Symbol selbst, so:

if (&UIApplicationWillEnterForegroundNotification != NULL) 
    etc; 

im Rückblick Welche Art liegt auf der Hand, aber ich bemängeln noch das gesamte Universum um mich, weil ich die Unterscheidung nie erwähnt habe.

+2

Wenn Sie LLVM verwenden, müssen Sie ein paar Tricks machen, damit es Ihre if-Anweisung nicht optomisiert. Das funktioniert für mich. BOOL backgroundOK = & UIApplicationDidEnterBackgroundNotification! = NULL; if (backgroundOK) { [[NSNotificationCenter defaultCenter] addObserver: self-Selektor: @selector (applicationDidEnterBackground :) Name: UIApplicationDidEnterBackgroundNotification bject: nil]; } –

+0

Verwenden von Vanille GCC, aber wenn LLVM es anders sieht, vermute ich, dass es ein Fehler von Apple sein kann (wie Apple explizit Entwicklern empfiehlt, diese Art der Laufzeitprüfung mit schwach verknüpften Symbolen zu tun) Schreiben Sie einen Testfall und senden Sie ihn unter http://bugreporter.apple.com an Apple. :) –

5

Hier ist was ich tun musste, wenn ich nach einer externen Rahmenkonstante suchte.

const CLLocationAccuracy * ptr = &kCLLocationAccuracyBestForNavigation; 
BOOL frameworkSupports = (ptr != NULL); 
if (frameworkSupports) { 
    return kCLLocationAccuracyBestForNavigation; 
} else { 
    return kCLLocationAccuracyBest; 
} 

Ohne die ptr-Variable würde es nicht funktionieren.

+0

>> Es würde ohne die Variable ptr nicht funktionieren. Andrew hat absolut Recht .. –