????????Catrgory & Extension
- Category 給原有的類擴(kuò)展特有的方法;
- Extension 可以擴(kuò)展變量、屬性,可以改寫(xiě)屬性的讀寫(xiě)屬性。
- 什么時(shí)候使用?
注意,下面的代碼示例是在 BLDemo2 當(dāng)中進(jìn)行的,即dragonView
??如何給類擴(kuò)充方法呢(自己創(chuàng)建的類,可以直接在里面創(chuàng)建方法很方便。一般使用 Category 都是給看不到源碼的庫(kù)),新創(chuàng)建一個(gè)OC文件,類型為 Category ,這里命名為 URL,Class 這里選擇 NSString 。

??創(chuàng)建出來(lái)之后它的命名方式很獨(dú)特,首先由 .h 和 .m 文件,其次名稱是 NSString+URL 。 在新創(chuàng)建的類中創(chuàng)建一個(gè)例子(僅僅是舉例), .h 文件中:
#import <Foundation/Foundation.h>
@interface NSString (URL)
- (BOOL)isURL;
@end
??在 .m 文件中寫(xiě)明方法:
#import "NSString+URL.h"
@implementation NSString (URL)
- (BOOL)isURL
{
if ([self hasPrefix:@"http://"]) {
return YES;
}
return NO;
}
@end
??如果以后真的需要判斷是不是URL,這樣的方法是不行的,還需要通過(guò)比如使用正則表達(dá)式等方法。
??接下來(lái)嘗試使用 Category 添加的方法,在 ViewController.m 中先導(dǎo)入 #import "NSString+URL.h":
- (void)viewDidLoad {
[super viewDidLoad];
NSString *url = @"www.baidu.com";
if ([url ifURL]) {
NSLog(@"是一個(gè)網(wǎng)址");
} else {
NSLog(@"不是一個(gè)網(wǎng)址");
}
}
??關(guān)于 Extension 增加成員變量就更佳地方便,可以直接在 ViewController.m 中操作:
@interface ViewController ()
{
BLDragonView *_dragonView1;
}
// 增加屬性就是這樣操作
@property(nonatomic, retain)BLDragonView *dragonView;
@end
??這樣的好處是在 ViewController 這個(gè)類中可以在任何地方對(duì) _dragonView1 進(jìn)行訪問(wèn)。
??關(guān)于 Extension 改寫(xiě)屬性的讀寫(xiě)屬性,比如在你在一個(gè)類的 頭文件聲明了一個(gè) NSString 類型的變量,并且只是具有 readonly 的特性,對(duì)外開(kāi)發(fā),但是后來(lái)你又希望把它改成對(duì)內(nèi)可讀寫(xiě)的,這時(shí)就可以在實(shí)現(xiàn)文件中通過(guò) Extension 改變它的屬性。
????????NSNotification
- 什么是通知?
??當(dāng)發(fā)生某件事情之后,將消息發(fā)送給所有的對(duì)象,對(duì)象收到通知后,就會(huì)進(jìn)行相應(yīng)的操作。代理 “主要” 是一對(duì)一的形式,通知一般為1對(duì)多。 - 什么時(shí)候用?
- 怎么用?
??通知的例子可以在 BLDragonView.m 中操作:
- (void)forwardButtonClicked:(id)sender
{
.......
NSDictionary *dic = @{@"name":@"123456", @"time":@"08:30"};
NSNotification *notification = [[NSNotification alloc] initWithName:@"BLDragonViewNotification"
object:nil
user:dic];
[[NSNotificationCenter defaultCenter] postNotification:notification];
// 通知類頭一個(gè)通知中心,固定在此處發(fā)送信息
// 使用異步線程處理通知,在通知多并且希望不阻塞主線程的情況下
[[NSNotificationQueue defaultQueue] enqueueNotification:notification
postingStyle:NSPostNow
coalesceMask:NSNotificationNoCoalescing // 合并類型意思是用什么方式將多個(gè)通知合并到一個(gè)通知,老師推薦是不合并
forModes:nil] // 模式一般傳nil
}
??如上通知就發(fā)送出去了,現(xiàn)在需要有類來(lái)接收通知,我們讓 ViewController 類來(lái)接收,在 .m 文件中:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self //添加一個(gè)觀察者 由我自己來(lái)檢測(cè)這個(gè)通知
selector:@selector(receiveDragonViewNotification:) // 收到這個(gè)通知之后我該做什么
name:@“BLDragonViewNotification:” // 通知的名字,注意這個(gè)名字一定是你發(fā)出的通知的名字,一一匹配
object:nil // 意思是要接哪一個(gè)對(duì)象的通知, 如果是接所有對(duì)象的話,就填 nil
}
// 然后需要實(shí)現(xiàn)接收到通知后的方法
- (void)receiveDragonViewNotification:(NSNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
NSLog(@"time is %@", [userInfo valueForKey:@"time"]);
}
......
??然后運(yùn)行應(yīng)用后,點(diǎn)擊前進(jìn)按鈕,就會(huì)發(fā)出通知, ViewController 類酒會(huì)接收到通知,然后打印出 key “time” 的鍵值。
??為了顯示通知一對(duì)多的特性,我們可以將接收通知在別的類中實(shí)現(xiàn),然后實(shí)現(xiàn)相應(yīng)的接收到通知后的方法。
??需要注意的一點(diǎn)是,因?yàn)榻邮毡O(jiān)聽(tīng)是系統(tǒng)方法,當(dāng) ViewController 類被釋放之后,這個(gè)監(jiān)聽(tīng)還是沒(méi)有被釋放,并且類沒(méi)有了就收不到信息了,這樣應(yīng)用繼續(xù)運(yùn)行是會(huì)導(dǎo)致崩潰的。一般這時(shí),就會(huì)運(yùn)用到 dealloc 方法。如何移出通知呢?在 ViewController.m 中:
- (void)dealloc
{
// [[NSNotificationCenter defaultCenter] removeObserver:self name: object:(id)]; 因?yàn)橐话氵@個(gè)類中或許需要監(jiān)聽(tīng)很多,所以方便效率起見(jiàn),會(huì)刪除所有,會(huì)如下:
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
??一定需要注意和掌握這個(gè)方法,很多初學(xué)者都會(huì)只設(shè)置監(jiān)聽(tīng),卻不移除,就會(huì)有可能在以后造成應(yīng)用的崩潰。
??還需要注意,通知的發(fā)出嗬監(jiān)聽(tīng)是同步的,意思就是例如當(dāng)你發(fā)出非常多的通知,很多類就會(huì)一個(gè)一個(gè)地去監(jiān)聽(tīng),做不了其他事情,如果接受完畢需要10分鐘,就代表將阻塞主線程10分鐘。(有時(shí)候應(yīng)用用著用著就不動(dòng)了,這很有可能就是主線程被阻塞掉了)所以當(dāng)你有非常多的通知需要發(fā)送時(shí),盡量不要在主線程中使用,使用異步的方法(看第五個(gè)代碼段最下面的代碼)。最后的效果是一樣的,就是不會(huì)造成阻塞主線程,一般情況下會(huì)使用post,根據(jù)具體情況選擇。
OC語(yǔ)法完成,ok!(后續(xù)學(xué)習(xí)查漏補(bǔ)缺~)