我有一個使用nw_path_monitor_t注冊網路事件的 func 。
// Entry point.
// Will be called from AppDelegate when app starts up
void TestNWPathMonitor () {
PrintToFile("TestingNWPathMonitor\n");
NotificationReceiver *notification_receiver = [[NotificationReceiver alloc] init];
// Set up the notification receiver to listen for wifi notification
[notification_receiver RegisterNotification];
monitor = nw_path_monitor_create ();
nw_path_monitor_set_update_handler (monitor, WifiNetworkChangeCB);
nw_path_monitor_start(monitor);
}
我已經提供了回呼,它將在網路事件發生變化時被呼叫。在回呼中(如下所示),我正在尋找 wifi 事件并向默認通知中心發布通知。
nw_path_monitor_update_handler_t WifiNetworkChangeCB = ^ (nw_path_t path) {
PrintToFile("Wifi Network change!!\n");
nw_path_status_t status = nw_path_get_status (path);
if (nw_path_uses_interface_type (path, nw_interface_type_wifi)) {
if (status == nw_path_status_satisfied) {
PrintToFile("nw_path_status_satisfied\n");
[[NSNotificationCenter defaultCenter] postNotificationName:@"WifiNetworkChange" object:nil];
} else {
PrintToFile("!(nw_path_status_satisfied)\n");
}
}
};
這是 NotificationReceiver 類:
// NotificationReceiver.h
#include <Foundation/Foundation.h>
@interface NotificationReceiver : NSObject
- (void) HandleNotification : (NSNotification *) pNotification;
- (void) RegisterNotification ;
@end
// NotificaitonReceiver.m
@implementation NotificationReceiver
- (void) HandleNotification : (NSNotification *) pNotification {
PrintToFile([[NSString stringWithFormat:@"Received notification: %@\n", pNotification.name] UTF8String]);
}
- (void) RegisterNotification {
PrintToFile("RegisterNotification!\n");
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(HandleNotification:) name:@"WifiNetworkChange" object:nil];
}
@end
在開始時呼叫的 RegisterNotification(如第一個代碼片段所示)將添加該實體作為觀察者,而 HandleNotification 是從 WifiNetworkChangeCB 塊發布的 wifi 通知的接收者。
The problem is, when I receive the wifi event, the WifiNetworkChangeCB is invoked and the postNotificationName function is executed (Have verified with the debugger), but HandleNotification doesn't receive the notification.
I'm getting the following output:
TestingNWPathMonitor
RegisterNotification!
Wifi Network change!!
Whereas, the expected output is:
TestingNWPathMonitor
RegisterNotification!
Wifi Network change!!
Received notification: WifiNetworkChange
I have read the documentation of the notification center to understand its usage. Have also referred this answer. I have also referred the documentation of the funcs I'm using (added them as hyperlinks while explaining the problem), everything seems fine.
But I'm obviously missing something (Since it didn't work). Any help will be greatly appreciated.
uj5u.com熱心網友回復:
原因:您的 C 函式進行了TestNWPathMonitor()分配,NotificationReceiver *notification_receiver但是當您離開作用域時,創建的物件沒有存盤在任何地方。因此,使用 ARC 記憶體管理,當作用域塊離開時,物件將被釋放,也就是它的堆疊再次“空”。
您的monitorakatypedef NSObject<OS_nw_path_monitor> *nw_path_monitor_t;似乎是一個全域變數,因此在離開范圍后它仍然存在,這可能會給您帶來誤解,即 objc 分配也是如此,是和否。同樣的情況也有happend到顯示幕,如果它本來是一個區域變數。
除錯:觀察[NSNotificationCenter defaultCenter]允許您幾乎在代碼中的任何位置捕獲通知,無論您等待它們的執行緒是什么,它是一個基于 NSString 的 API,其優點和缺點都有其充分的理由。由于這種簡單的方法,很難找到它不起作用的原因。但基本上放置一個觀察者main.m或APPDelegate應該總是告訴你它是否在發布端正常作業,以確保你沒有拼錯NotificationName. 為了避免后一種情況,我們經常宣告
extern NotificationName const kSomeNiceNotification;
// in .h && the following in .m
NotificationName const kSomeNiceNotification = @"kSomeNiceNotification";
并使用此全域鍵作為名稱。
提示:您還可以創建一個單一的通知,該通知將在收到時觸發并銷毀自身,并在執行此操作時必須考慮其他含義。像這樣(來自 Xcode 檔案)。
NSNotificationCenter * __weak center = [NSNotificationCenter defaultCenter];
id __block token = [center addObserverForName:@"OneTimeNotification"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
NSLog(@"Received the notification!");
[center removeObserver:token];
}];
看到[NSOperationQueue mainQueue]上面的代碼片段了嗎?您可以通過nil那里,但是通知塊將在發送通知的執行緒上執行。當在 UI 代碼中使用時,這通常是通知的用例,這很重要,因為 UI 任務需要在主執行緒上執行,在主執行緒中傳遞nil迫使您稍后將 UI 內容包裝在
dispatch_async(dispatch_get_main_queue(), ^{ /* UI code block */ }); // or
dispatch_sync(dispatch_get_main_queue(), ^{ /* UI code block */ });
當您告訴通知觀察者在收到通知塊時執行通知塊的位置時,您不需要這樣做。
Ps:在 objc 中,我們以小寫字母開頭方法名,當 setter 和 getter 違反“camelCased”方法名規則時,您會遇到麻煩,因為介面@property NSObject *someName;變得與現代 objc 一樣成為-(NSObject*)someName;getter 和-(void)setSomeName:(NSObject*)somename;setter。這也說明了為什么我們使用較低的下劃線來標??記幾乎所有屬性的對應物的區域類變數..在這個給定的示例中,該屬性NSObject *someName將具有內部_someName對應物。這里不會像在 oldschool objc 中那樣深入,有更多關于類宣告的@dynamic ...資訊@synthesize ...,并且允許更詳細地控制(內部)本地類變數名稱。
為什么要為此煩惱?您的NotificationReceiver *notification_receiver可以覆寫具有相同名稱的類屬性,給您的印象是您所做的一切都是正確的,但仍然無法正常作業,因為宣告仍然會使堆疊為空。因此,像_notification_receiver = ...在方法/功能塊中一樣宣告變數會很清楚你的意思是它的內部對應物,@property NotificationReceiver *notification_receiver;而不是一個額外的區域變數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/335885.html
標籤:ios objective-c macos nsnotificationcenter nwpathmonitor
上一篇:通用有界引數與自身不兼容
