2014-10-29 10 views
10

verwenden Zieht meine Haare aus CFNotificationCenterAddObserver zu arbeiten in Swift.Wie man korrekt CFNotificationCenterAddObserver in Swift für iOS

 CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 
     UnsafePointer<Void>(self), 
     iosLocked, 
     "com.apple.springboard.lockcomputer" as CFString, 
     nil, 
     CFNotificationSuspensionBehavior.DeliverImmediately) 

Die iOS docs haben sie aufgelistet und ich habe unzählige Iterationen auf dem Rückruf und die unsicheren Zeiger ohne Erfolg versucht.

Der Aufruf über Funktionsergebnisse in dieser Fehlermeldung, die die korrekte init zu sein scheint:

Cannot invoke 'init' with an argument list of type '(CFNotificationCenter!, $T4,() ->(), CFString, NilLiteralConvertible, CFNotificationSuspensionBehavior)' 

ich als this post here schlägt ObjC Überbrückung auch versucht, aber ohne Erfolg.

Hier ist meine Brücke:

LockNotifierCallback.h:

#import <Foundation/Foundation.h> 

@interface LockNotifierCallback : NSObject 

+ (void(*)(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo))notifierProc; 

@end 

und LockNotifierCallback.m:

#import "LockNotifierCallback.h" 

static void lockcompleteChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 
    NSLog(@"success"); 
} 

@implementation LockNotifierCallback 


+ (void(*)(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo))notifierProc { 
    return lockcompleteChanged; 
} 

@end 

mit Aufruf aktualisiertem CFNotificationCenterAddObserver wie folgt:

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 
     LockNotifierCallback.notifierProc, 
     iosLocked, 
     "com.apple.springboard.lockcomputer" as CFString, 
     nil, 
     CFNotificationSuspensionBehavior.DeliverImmediately) 

und natürlich LockNotifierCallback.h ist in meinem Bridging-Header. Fehler weiter:

Cannot convert the expression's type '(CFNotificationCenter!,() -> CFunctionPointer<((CFNotificationCenter!, UnsafeMutablePointer<Void>, CFString!, UnsafePointer<Void>, CFDictionary!) -> Void)>,() ->(), CFString, NilLiteralConvertible, CFNotificationSuspensionBehavior)' to type 'StringLiteralConvertible' 
+2

'CFNotificationCenterAddObserver' nimmt einen' CFunctionPointer' die Sie können nicht wirklich von Swift erstellen (siehe http://StackOverflow.com/a/25514748/3300036). Sie können umgehen, indem Sie einige Objective-C-Bridging ähnlich wie folgt tun: http://stackoverflow.com/a/26139259/3300036 –

+1

Danke Mark, aber warum würde es unter einer schnellen Deklaration in den IOS-Dokumenten sein? https://developer.apple.com/Library/ios/documentation/CoreFoundation/Reference/CFNotificationCenterRef/index.html#//apple_ref/c/func/CFNotificationCenterAddObserver – zooster

+1

Sie können es immer noch von Swift verwenden, Sie müssen es nur übergeben eine Funktion, die in C oder Objective-C definiert ist und keine Swift-Funktion des Abschlusses. –

Antwort

9

ich mit DarwinNotifications hatte einige Probleme, können Sie versuchen, diese Wrapper-Klasse mit nur Header-Datei in Ihrer Überbrückung Datei enthalten. Und Sie können es in swift verwenden.

DarwinNotificationsManager.h:

#import <Foundation/Foundation.h> 

#ifndef DarwinNotifications_h 
#define DarwinNotifications_h 

@interface DarwinNotificationsManager : NSObject 

@property (strong, nonatomic) id someProperty; 

+ (instancetype)sharedInstance; 

- (void)registerForNotificationName:(NSString *)name callback:(void (^)(void))callback; 
- (void)postNotificationWithName:(NSString *)name; 

@end 

#endif 

DarwinNotificationsManager.m:

#import <Foundation/Foundation.h> 
#import "DarwinNotificationsManager.h" 


@implementation DarwinNotificationsManager { 
    NSMutableDictionary * handlers; 
} 

+ (instancetype)sharedInstance { 
    static id instance = NULL; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     instance = [[self alloc] init]; 
    }); 
    return instance; 
} 

- (instancetype)init { 
    self = [super init]; 
    if (self) { 
     handlers = [NSMutableDictionary dictionary]; 
    } 
    return self; 
} 

- (void)registerForNotificationName:(NSString *)name callback:(void (^)(void))callback { 
    handlers[name] = callback; 
    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter(); 
    CFNotificationCenterAddObserver(center, (__bridge const void *)(self), defaultNotificationCallback, (__bridge CFStringRef)name, NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 
} 

- (void)postNotificationWithName:(NSString *)name { 
    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter(); 
    CFNotificationCenterPostNotification(center, (__bridge CFStringRef)name, NULL, NULL, YES); 
} 

- (void)notificationCallbackReceivedWithName:(NSString *)name { 
    void (^callback)(void) = handlers[name]; 
    callback(); 
} 

void defaultNotificationCallback (CFNotificationCenterRef center, 
       void *observer, 
       CFStringRef name, 
       const void *object, 
       CFDictionaryRef userInfo) 
{ 
    NSLog(@"name: %@", name); 
    NSLog(@"userinfo: %@", userInfo); 

    NSString *identifier = (__bridge NSString *)name; 
    [[DarwinNotificationsManager sharedInstance] notificationCallbackReceivedWithName:identifier]; 
} 


- (void)dealloc { 
    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter(); 
    CFNotificationCenterRemoveEveryObserver(center, (__bridge const void *)(self)); 
} 


@end 

In swift Sie es wie folgt verwenden können:

let darwinNotificationCenter = DarwinNotificationsManager.sharedInstance() 
darwinNotificationCenter.registerForNotificationName("YourNotificationName"){ 
      //code to execute on notification 
} 
+0

Wenn Hintergrund-App-Refresh aktiviert ist, wird die App beim Empfang einer Darwin-Benachrichtigung vom Hintergrund aktiviert, um Code auszuführen, wie es bei Remote-Benachrichtigungen der Fall wäre? – user2363025