練習(xí)與示例:
1.代理
- 新建Boss類器躏,在.h中聲明其方法和代理屬性:
@protocol NannyDelegate <NSObject>
- (void)washClothes;
- (void)cook;
@optional
- (void)takeCareBaby;
@end
@interface Boss : NSObject
//實(shí)現(xiàn)了這個(gè)協(xié)議的任意類型的對(duì)象
// 代理屬性要用assign和weak去修飾,不需要使用oc中的內(nèi)存管理
@property (nonatomic, assign)id<NannyDelegate>delegate;
-(void)clothesDirty;
-(void)hungry;
-(void)working;
@end
- 在.m中實(shí)現(xiàn)方法:
-(void)clothesDirty {
NSLog(@"衣服臟了");
[self.delegate washClothes];
}
-(void)hungry {
NSLog(@"餓了");
[self.delegate cook];
}
-(void)working {
NSLog(@"去上班");
// 判斷我的代理人能否響應(yīng)(是否實(shí)現(xiàn))某方法
if ([self.delegate respondsToSelector:@selector(takeCareBaby)]) {
[self.delegate takeCareBaby];
} else {
NSLog(@"帶孩子去上班");
}
}
- 新建一個(gè)Worker類碉就,導(dǎo)入頭文件并繼承Boss類的代理:
#import "Boss.h"
@interface Worker : NSObject<NannyDelegate>
- 在.h中實(shí)現(xiàn):
- (void)washClothes {
NSLog(@"洗衣服");
}
//- (void)cook {
// NSLog(@"做飯");
//}
- (void)cook {
NSLog(@"zuofan");
}
- (void)takeCareBaby {
NSLog(@"保姆照顧孩子");
}
- 在主函數(shù)中導(dǎo)入頭文件:
#import "Boss.h"
#import "Worker.h"
- 在主函數(shù)中實(shí)現(xiàn):
Boss *boss = [[Boss alloc]init];
Worker *worker = [[Worker alloc]init];
boss.delegate = worker;
[boss hungry];
[boss clothesDirty];
[boss working];
2.類的擴(kuò)展
- 新建OC文件SayHi為NSString類,在.h中進(jìn)行方法的聲明:
- (void)sayHi;
- (void)getCharacterOfPre;
// 為NSString類擴(kuò)展一個(gè)新的方法坤按,要求獲取字符串的首字母并且將該首字母大寫弃衍。
- (NSString *)firstCharacter;
- 在.m中進(jìn)行實(shí)現(xiàn):
- (void)sayHi {
NSLog(@"我是%@,我是一個(gè)牛逼的字符串", self);//self指的是當(dāng)前調(diào)用這個(gè)方法的字符串對(duì)象
}
- (void)getCharacterOfPre {
NSString *s = [[self substringToIndex:1] capitalizedString];
NSLog(@"%@", s);
}
- (NSString *)firstCharacter {
if (self.length > 0) {
return [[self substringToIndex:1] uppercaseString];
}
NSLog(@"空字符串別湊熱鬧");
return @"";//或者寫nil或self
}
- 在主函數(shù)中進(jìn)行頭文件導(dǎo)入:
#import "NSString+SayHi.h"
- 在主函數(shù)中進(jìn)行調(diào)用:
int main(int argc, const char * argv[]) {
[@"徐博杰" sayHi];
[@"dfdf" getCharacterOfPre];
NSLog(@"%@", [@"abc" firstCharacter]);
return 0;
}
- 新建一個(gè)Person類燎孟,在.m中自定義初始化方法:
@interface Person ()
@property(nonatomic, retain) NSString *age;
@end
@implementation Person
- (instancetype)init
{
self = [super init];
if (self) {
//私有方法通常是通過其它方法間接調(diào)用禽作,目的是將某一部分的代碼分裝起來,多次使用
[self sayHi];
}
return self;
}
// 沒在.h中聲明的都是私有方法
- (void)sayHi {
NSLog(@"hahahaha");
}
@end
3.省市區(qū)
NSMutableArray *provinceArray = [NSMutableArray array];
// 加載文件得到字符串
// 參數(shù)一:文件路徑
// 參數(shù)二:編碼格式
// 參數(shù)三:錯(cuò)誤信息
NSString *contentString = [NSString stringWithContentsOfFile:@"area.txt" encoding:NSUTF8StringEncoding error:nil];
// NSLog(@"%@", contentString);
// 以換行符分割字符串揩页,得到每一行的字符串內(nèi)容
NSArray *lineArray = [contentString componentsSeparatedByString:@"\n"];
for (NSString *lineString in lineArray) {
// NSLog(@"line:%@", lineString);
if (![lineString hasPrefix:@" "]) {
// 前綴不是空格是省名
// 創(chuàng)建一個(gè)省份字典
NSMutableDictionary *provinceDic = [NSMutableDictionary dictionary];
// 省份字典添加鍵值對(duì)(provinceName:省份名)
[provinceDic setObject:lineString forKey:@"provinceName"];
// 創(chuàng)建一個(gè)城市數(shù)組(用于后面存放城市字典)
NSMutableArray *cityArray = [NSMutableArray array];
// 添加鍵值對(duì)(cityName:城市名)
[provinceDic setObject:cityArray forKey:@"cityArray"];
[provinceArray addObject:provinceDic];
} else if (![lineString hasPrefix:@" "]) {
// 前綴有空格且不是四個(gè)空格為城市名
// 讀取到城市名的時(shí)候需要找到該城市所屬省份(當(dāng)前省份數(shù)組中最后一個(gè)元素就是當(dāng)前城市所屬省份)
NSMutableDictionary *provinceDic = [provinceArray lastObject];
NSMutableArray *cityArray = [provinceDic objectForKey:@"cityArray"];
// 創(chuàng)建城市字典
NSMutableDictionary *cityDic = [NSMutableDictionary dictionary];
// 添加鍵值對(duì)(cityName:城市名)
[cityDic setObject:lineString forKey:@"cityName"];
//創(chuàng)建地區(qū)數(shù)組(后面用于存放地區(qū)名稱)
NSMutableArray *areaArray = [NSMutableArray array];
// 添加鍵值對(duì)(areaArray:地區(qū)數(shù)組)
[cityDic setObject:areaArray forKey:@"areaArray"];
//將城市的字典存到對(duì)應(yīng)的城市數(shù)組中
[cityArray addObject:cityDic];
} else {
// 前綴有空格且有四個(gè)空格的為地區(qū)名
// 獲取當(dāng)前地區(qū)所在省份
NSMutableDictionary *provinceDic = [provinceArray lastObject];
// 獲取該省份的城市數(shù)組
NSMutableArray *cityArray = [provinceDic objectForKey:@"cityArray"];
// 從城市數(shù)組中獲取當(dāng)前城市所屬城市
NSMutableDictionary *cityDic = [cityArray lastObject];
// 獲取該城市的地區(qū)數(shù)組
NSMutableArray *areaArray = [cityDic objectForKey:@"areaArray"];
// 將地區(qū)名存到該地區(qū)數(shù)組
[areaArray addObject:lineString];
}
}
for (NSMutableDictionary *provinceDic in provinceArray) {
NSLog(@"省份:%@", [provinceDic objectForKey:@"provinceName"]);
for (NSMutableDictionary *cityDic in [provinceDic objectForKey:@"cityArray"]) {
NSLog(@"城市:%@", [cityDic objectForKey:@"cityName"]);
for (NSString *areaName in [cityDic objectForKey:@"areaArray"]) {
NSLog(@"地區(qū):%@", areaName);
}
}
}
知識(shí)點(diǎn):
1.屬性的內(nèi)存管理
語義特性 使用范圍
assign 基本數(shù)據(jù)類(char, short, int, float, double)
retain 對(duì)象類型
copy 對(duì)象類型旷偿,且遵守了<NSCopying>協(xié)議
2.集合的內(nèi)存管理
1??常見的集合類有:NSArray,NSDictionary,NSSet萍程。
2??集合會(huì)自主管理集合內(nèi)部元素幢妄。
3??集合內(nèi)存管理的方式:
加入集合的元素會(huì)被retain;
移除出集合的元素會(huì)被release;
集合被釋放時(shí),會(huì)對(duì)集合中所有元素release;
3.KVC
1??KVC:Key Value Coding茫负,鍵值編碼蕉鸳,是一種間接訪問實(shí)例變量的方法。
2??KVC提供了一種使用字符串(key)而不是訪問器方法忍法,去訪問一個(gè)對(duì)象實(shí)例變量的機(jī)制潮尝。
3??KVC中常用的方法:
- (id)valueForKey:(NSString *)key;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
4??KVC按順序使用如下技術(shù):
1)、檢查是否存在getter方法-<key>或者setter方法-set<key>:的方法缔赠;
2)衍锚、如果沒有上述方法,則檢查是否存在名字為-_<key>嗤堰、<key>的實(shí)例變量戴质;
3)、如果仍未找到踢匣,則調(diào)用valueForUndefinedKey:和setValue:forUndefinedKey:方法告匠。這些方法的默認(rèn)實(shí)現(xiàn)都是拋出異常,我們可以根據(jù)需要重寫它們离唬。
4.ARC
ARC:Automatic Reference Counting后专,自動(dòng)引用計(jì)數(shù),由開發(fā)人員開辟內(nèi)存空間输莺,但是不需要釋放該內(nèi)存空間戚哎,由系統(tǒng)自動(dòng)釋放該空間。
ARC本質(zhì)上還是基于MRC的嫂用,只不過是系統(tǒng)自動(dòng)添加了釋放內(nèi)存的方法型凳。
ARC是編譯器特性,而不是運(yùn)行時(shí)特性嘱函,更不是垃圾回收器(GC)甘畅。
從Xcode5.0后,創(chuàng)建的工程默認(rèn)是開啟ARC的往弓。
當(dāng)工程開啟ARC后疏唾,由于編譯器會(huì)自動(dòng)幫你釋放內(nèi)存,所有和內(nèi)存相關(guān)操作retain函似、release槐脏、autorelease,都不能寫缴淋。
當(dāng)重寫dealloc方法時(shí)准给, 也不能寫[super dealloc]泄朴,否則會(huì)報(bào)錯(cuò)重抖。
ARC中的屬性語義特性:
語義特性 使用范圍
assign 基本數(shù)據(jù)類(char, short, int, float, double)
strong 對(duì)象類型露氮,相當(dāng)于MRC中的retain
copy 對(duì)象類型,且遵守了<NSCopying>協(xié)議
weak 對(duì)象類型钟沛,但是內(nèi)部不會(huì)對(duì)對(duì)象做retain的操作
ARC與MRC的混編:
如果需要對(duì)特定文件開啟或關(guān)閉ARC畔规,可以在工程選項(xiàng)中選擇Targets -> Compile Phases -> Compile Sources,在里面找到對(duì)應(yīng)文件恨统,添加flag:
打開ARC:-fobjc-arc
關(guān)閉ARC:-fno-objc-arc
5.總結(jié)
1??assign叁扫、retain、copy對(duì)應(yīng)不同的setter實(shí)現(xiàn)畜埋。為實(shí)例變量賦值時(shí)莫绣,盡量使用setter方法,再次賦值時(shí)悠鞍,會(huì)把之前值release对室。
2??dealloc在對(duì)象引用計(jì)數(shù)為0時(shí)自動(dòng)調(diào)用,不要顯示調(diào)用咖祭。dealloc實(shí)現(xiàn)內(nèi)部掩宜,先要釋放實(shí)例變量,然后執(zhí)行[super dealloc]么翰。
3??便利構(gòu)造器的內(nèi)存管理是借助autorelease實(shí)現(xiàn)的牺汤。
4??集合會(huì)管理自己的元素。
5??KVC是一種間接訪問實(shí)例變量的方法浩嫌。
6??ARC系統(tǒng)管理內(nèi)存檐迟,不需要開發(fā)人員手動(dòng)管理。