NSNotification Name 最佳寫法

本文主要借探討NSNotificationName的最佳寫法的機會,學習下extern, static, const, #define 和常量指針與指針常量等的特性和用法。post

1.NSNotification標準使用方法

發送通知學習

[[NSNotificationCenter defaultCenter] postNotificationName:QLPosterDidPostNotification object:nil];

接收通知spa

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceive:) name:QLPosterDidPostNotification object:nil];


還要注意在dealloc中移除通知哈指針

 

2.通知的發送者和接收者都須要知道NSNotification name,如何保證雙方統一

在iOS中,通知是爲了方便解耦,所以通知的發送者和接收者每每不在同一個類/文件中code

可是不管是發送者仍是接收者,他們使用的通知名字卻須要一致,如上例的QLPosterDidPostNotification在兩處地方都使用到了server

那麼如何保證2處地方使用的通知名字是同一個呢?blog

最蠢的作法就是在各處須要用到這個通知的地方本身定義一個QLPosterDidPostNotification內存

這種作法違背了DRY原則,簡直忍無可忍,一旦違背了DRY原則,代碼的可讀性將會變得很是差,維護起來會很是噁心!ci

最佳實踐是一處地方定義,多處地方使用編譯器

 

3.最佳寫法

QLPoster.h

extern NSString *const QLPosterDidPostNotification;

QLPoster.m

NSString *const QLPosterDidPostNotification = @"QLPosterDidPostNotification";

QLReceiver.h

extern NSString *const QLPosterDidPostNotification;

 

4.怎麼用

首先,很天然的,咱們先在QLPoster.m中聲明定義一個通知的名字

NSString *const QLPosterDidPostNotification = @"QLPosterDidPostNotification";

其次,爲了讓外面的人統一使用該變量,咱們須要在QLPoster.h中將該變量暴露出去,而且加上extern,但不須要賦值(由於是聲明)。目的就是爲了告訴外部調用者,我有QLPosterDidPostNotification這個變量,它是什麼內容大家別管,直接用就好了

而後QLReceiver要來調用啦,直接把QLPoster.h中關於變量聲明的這句代碼直接copy到本身的.h就行啦(由於這也是聲明)

 

5.爲何不用#define

static const 是十分常見的組合,這裏能夠先把問題轉爲 static const 和 #define 的區別。

static const和#define的異同是:

相同點:編譯器根本不會建立符號,預編譯時把全部遇到的變量都替換爲常值

不一樣點:可是static const定義的常量帶有類型信息(能夠指明常量是int, double, ...),便於理解

因爲#define定義的常量不含類型信息,編譯器只是會在編譯前據此執行查找與替換操做。即便有人從新定義了常量值,編譯器也不會產生警告信息,這將致使應用程序中的常量不一致

 

6.extern是什麼(爲何不用static const)

extern int a;//聲明一個全局變量a
int a; //定義一個全局變量a
extern int a = 0 ;//定義一個全局變量a並給初值
int a = 0;//定義一個全局變量a並給初值

定義只能有1處,但聲明能夠有多處

定義引發內存分配,聲明則不會

A.m

NSString *hello = @"hello";

B.m中不須要#import "A.m",直接

extern NString *hello;
NSLog(@"%@", hello);    //輸出 hello

 

很是厲害,不須要引用相關頭文件就能使用其值!

變量的聲明默認就是extern

變量的聲明默認就是extern

變量的聲明默認就是extern

重要的事情說3次了

假如A.m不想被B用extern找到,怎麼辦?只須要加個static

A.m

static NSString *hello = @"hello";

static表示該值只會在本文件(.m)中使用哈,別人看不到的

假如聲明此變量時不加static,則編譯器會爲它建立一個「外部符號」(external symbol)

假如C.m也和A.m同樣,都有一個NSString *hello = @"hello";

那就會編譯失敗,由於有2個外部變量hello

 

7.爲何加const

通知名稱通常是固定不可變的,且不但願外部修改其值,因此加上const無非是最正確的選擇

 

8.爲何是NSString *const 而不是 NSString const *

這就是C/C++中說到的常量指針和指針常量的區別了

const寫在*前面,則該指針可被從新賦值,而指針指向的內容不可被從新賦值

const寫在*後面,則該指針指向的內容可被從新賦值,而指針自己不可被從新賦值(即不能指向其餘內存)

回到iOS中來,咱們修改NSString的值,是怎麼修改

NSString *str = @"123";
str = @"456";

注意哦,str = @"456";至關於(不表明就必定是)str = [[NSString alloc] initWithString:"456"];

就是說,iOS中,對NSString的修改通常都是讓其指向一塊新的內存

因此爲了防止外部改變通知名字的值,咱們通常將const寫在*後面


9.規範的NSNotification Name命名方式

[Name of associated class] + [Did | Will] + [UniquePartOfName] + Notification

(1)QLPosterDidPostNotification 而不是 kDidPostNotification

以k開頭的通常是類內本身使用的static const變量,若是須要提供給外部使用,最好將本身的類名做爲前綴

通知通常都不是隻給本身用的,因此須要將本身的類名做爲前綴

聲明爲extern的常量要出如今全局符號表中,因此其名稱應加以區隔,一般用與之相關的類名作前綴。

(2)Did/Will表示動做的已經結束或即將開始,以明確通知拋出的時機

(3)QLPosterDidPostNotification 而不是 QLPosterDidPostNoti

通知名稱這裏寧願名字長也不要引發歧義(蘋果的命名一貫被吐槽太長了)

相關文章
相關標籤/搜索