ios - 如何在 Swift for iOS 中正确使用 CFNotificationCenterAddObserver

标签 ios swift notifications darwin

CFNotificationCenterAddObserver 在 Swift 中工作让我大吃一惊。

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

iOS docs列出它,我已经在回调和不安全指针上尝试了无数次迭代,但没有成功。

上面的函数调用导致了这个错误消息,这似乎是正确的初始化:

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

我还尝试桥接到 objc 为 this post here建议,但没有成功。

这是我的桥梁:

LockNotifierCallback.h:

#import <Foundation/Foundation.h>

@interface LockNotifierCallback : NSObject

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

@end

和 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

更新后的 CFNotificationCenterAddObserver 调用如下:

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

当然 LockNotifierCallback.h 在我的桥接头中。错误继续:

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

最佳答案

我在使用 DarwinNotifications 时遇到了一些问题,您可以尝试使用这个包装类 只需在桥接文件中包含头文件即可。您可以快速使用它。

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

在 swift 中你可以像这样使用它:

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

关于ios - 如何在 Swift for iOS 中正确使用 CFNotificationCenterAddObserver,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26637023/

相关文章:

ios - 发布后更新 TableView

iOS UITableView.AutomaticDimension 不工作

swift - 如何快速复制一个只有一个不同字段的结构

android - 应用程序在后台/未运行时如何设置自定义通知声音?

php - 带列表的 Redis 通知

ios - 如何将按钮放置在屏幕下半部分的中央

ios - 多区域拉伸(stretch)图像

ios - 旋转屏幕时,带有嵌入 tableview 的 Collectionview 会被剪裁

ios - 着陆重复事件不起作用

android - GCM 3.0 - gcm 不会自动显示带有通知参数的通知