- 面向對象三大支柱
封裝:就是把相關的數(shù)據(jù)和代碼結合成一個有機的整體氮帐,形成數(shù)據(jù)和操作代碼的封裝體嗅虏,對外只提供一個可以控制的接口,內部大部分的實現(xiàn)細節(jié)對外隱蔽上沐,達到對數(shù)據(jù)訪問權的合理控制皮服。
繼承:從已有的類創(chuàng)建新類的過程,提供繼承信息的稱為父類,得到繼承信息的稱為子類龄广,之類和父類之間是IS-A關系硫眯。
多態(tài):不同結構的對象可以以各自不同的方式響應同一個消息,或者或同一個消息可以根據(jù)發(fā)送消息的對象的不同采用多種不同的操作行為择同。重寫是對父類的方法給出新的實現(xiàn)版本两入,重寫是實現(xiàn)多態(tài)性的重要步驟。由于不同的子類對父類方法進行重寫時可以給出各自的實現(xiàn)版本敲才,因此他們收到相同的消息時會表現(xiàn)出不同的行為裹纳,這就是所謂的多態(tài)。有了多態(tài)我們可以通過父類型的指針指向子類紧武,然后向子類對象發(fā)出消息剃氧,父類指針可以指向任意子類對象。
CDCircle *circle = [CDCircle circleWithRadius:10 x:0 y:0];
CDRect *rect = [CDRect rectWithWidth:10 heigth:20 x:0 y:0];
CDDBTriangle *tri = [CDDBTriangle triangleWithEdge:5 x:0 y:0];
NSArray *array = @[circle, rect, tri];
// 定義一個對象指針類型的時候盡可能使用父類型的指針
// 因為父類型的指針可以指向子類對象(上轉型)
// 使用父類型的指針可以讓程序的通用性更強
for (CDShape *tempShape in array) {
// 同樣的指針 調用同樣的方法(發(fā)同樣的消息)
// 但是繪制出了不同的圖形 這就是多態(tài)
// OC的消息機制是: 不看指針看對象
[tempShape draw];
NSLog(@"周長: %f", tempShape.perimeter);
NSLog(@"面積: %f", tempShape.area);
}```
- 面向對象的編程原則
- 單一職責原則(SRP): 設計一個類應該只圍繞一個主題或中心思想服務阻星;設計一個方法應該只做好一件事情朋鞍。
- 開閉原則(OCP): 好的軟件實體只接受擴展不接受修改。抽象是關鍵妥箕,用繼承結構封裝可變性(隔離程序中不同的可變因素)滥酥。
- 依賴倒轉原則(DIP): 要面向抽象編程不要面向實現(xiàn)編程。聲明指針變量的類型畦幢、方法的參數(shù)類型恨狈、方法的返回類型時盡可能使用父類型指針或協(xié)議指針(id<協(xié)議>),不要使用具體類型(子類型)指針呛讲。
- 里氏替換原則(LSP): 任何時候用子類對象替換父類型對象都是可以的,但是反過來通常是不成立的返奉。子類能力比父類能力更多贝搁,用能力多的替換能力少的當然可以,反之未必成立芽偏。
- 接口隔離原則(ISP): 協(xié)議小而專雷逆,不能大而全。不能夠將不相關的方法組織到一個協(xié)議中污尉,這樣會模糊協(xié)議所表示的角色膀哲。
- 合成聚合復用原則(CARP) : 優(yōu)先考慮用強關聯(lián)關系復用代碼而不是使用繼承。- 方法的命名應當使用駝峰標識(Camel Notation)被碗。
- C語言字符串(字符數(shù)組)的賦值不能使用= 要使用字符串拷貝函數(shù)
strcpy(name, _name);
// 1. 用符號常量替換字面常量
// 2. 用const定義常量而不是用宏定義常量
static const double FENCE_PRICE = 25.5; ```
- 類方法
跟類的對象狀態(tài)無關的方法某宪,它屬于類不屬于對象,類方法的調用只能通過類名來調锐朴,類方法不能使用成員變量(成員變量屬于某個特定的對象)。 - Class也是一種類型
Class catClass = [CDCat class]; CDCat *cat = [[catClass alloc] init]; [cat catchTheMouse];
Class dogClass = NSClassFromString(@"CDDog"); CDDog *dog = [[dogClass alloc] init]; [dog keepTheDoor];
for (CDPerson *tempPerson in persons) {
[tempPerson eat:@"盒飯"];
[tempPerson play:@"麻將"];
// RTTI
// (運行時類型識別 RunTime Type Identification)
if ([tempPerson isKindOfClass:[CDStudent class]]) {
[tempPerson performSelector:@selector(study:) withObject:@"C語言"];
}
else if ([tempPerson isKindOfClass:[CDTeacher class]]) {
[tempPerson performSelector:@selector(teach:) withObject:@"HTML網(wǎng)頁設計"];
}
}```
SEL是一種類型,它是代表對象方法的類型漓雅,它的值相當于是一個對象方法的標識符,可以通過此標識符調用對象的方法畏鼓,類似C語言中指向函數(shù)的指針,可以通過擴展指令@selector獲得方法的選擇器壶谒。
void bar(id obj, SEL sel, id param) {
// 給對象發(fā)由選擇器指定的消息(執(zhí)行選擇器)
// 通過NSObject的respondsToSelector:方法可以判定對象
// 是否能夠接收指定的消息(對選擇做出響應)
if ([obj respondsToSelector:sel]) {
// 如果對象不能接收指定的消息 程序會崩潰
// 上面的if判斷可以確保對象不會執(zhí)行無法識別的選擇器
pragma clang diagnostic push
pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[obj performSelector:sel withObject:param];
pragma clang diagnostic pop
}
}```
- 單例模式
避免重復創(chuàng)建對象云矫,減少對象狀態(tài)混亂或者內存耗費問題。要點:1.阻止使用構造方法初始化對象汗菜。2.使用類方法向外界提供該類的唯一實例让禀。
-(instancetype) init {
@throw [NSException exceptionWithName:@"初始化對象異常" reason:@"不允許通過初始化方法創(chuàng)建對象" userInfo:nil];
}
+(instancetype) sharedManager {
static CDBookManager *sharedManager = nil;
// 同步保護 (只允許一個線程進入下面的代碼塊執(zhí)行 如果有多個線程 其他線程需要排隊等待之前進入的線程離開同步塊以后才能進入同步塊 這樣即便在多線程環(huán)境下也能保證該類只能創(chuàng)建出一個對象)
@synchronized (self) {
if (!sharedManager) {
sharedManager = [[self alloc] initPrivate];
}
}
return sharedManager;
}```
- 枚舉
//typedef enum { UP, DOWN, LEFT, RIGHT } Direction;
typedef NS_ENUM(NSUInteger, Direction) {
UP = 1 << 0,
DOWN = 1 << 1,
LEFT = 1 << 2,
RIGHT = 1 << 3
};
- NSEnumerator
// 迭代器遍歷
NSEnumerator *en = [array3 reverseObjectEnumerator];
NSString *str = nil;
while(str = [en nextObject]) {
NSLog(@"%@", str); }```
- 數(shù)組排序
- 方法1:sortUsingDescriptors (使用排序描述符對象描述排序規(guī)則)
NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:@"xyz" ascending:YES];
NSArray *descArray = [[NSArray alloc] initWithObjects:&desc count: 1];
[mArray sortUsingDescriptors:descArray]; ```
Example:
// 通過指定排序描述符對象對玩家手上的撲克進行排序
NSSortDescriptor *suiteDesc = [[NSSortDescriptor alloc] initWithKey:@"suite" ascending:YES];
NSSortDescriptor *faceDesc = [[NSSortDescriptor alloc] initWithKey:@"face" ascending:YES];
// 按照數(shù)組的書寫順序 suiteDesc是第一排序關鍵字 faceDesc是第二排序關鍵字 也就是說先比花色 花色相同再比點數(shù)
[cardsOnHand sortUsingDescriptors:@[suiteDesc, faceDesc]];```
- 方法2:sortUsingComparator (使用block語法將比較規(guī)則傳入排序方法中)
NSComparator comp = ^(id obj1, id obj2) {
if(obj1.prop == obj2.prop) {
return NSOrderedSame;
}
else {
return book1.prop < book2.prop? NSOrderedAscending : NSOrderedDescending;
}
};
[mArray sortUsingComparator:comp]; ```
- 方法3:sortUsingSelector (通過為對象提供比較方法支持排序)
-(NSComparisonResult) compare:(CDBook *) other {
if(self.counter - other.counter == 0) {
return NSOrderedSame;
}
else {
return self.counter > other.counter? NSOrderedAscending : NSOrderedDescending;
}
}```
NSArray *array = @[@"quick", @"fuck", @"duck", @"earthquake"];
// NSArray *sortedArray = [array sortedArrayUsingSelector:@selector(compare:)];
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
return [obj1 compare:obj2];
}];
NSArray *array = @[@10, @5, @99, @36, @20];
// NSArray *sortedArray = [array sortedArrayUsingSelector:@selector(compare:)];
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2];
}];
NSArray *array = @[
[[CDPerson alloc] initWithName:@"王大錘" age:24],
[[CDPerson alloc] initWithName:@"駱昊" age:35],
[[CDPerson alloc] initWithName:@"李小龍" age:32],
[[CDPerson alloc] initWithName:@"張三豐" age:120]];
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(CDPerson *obj1, CDPerson *obj2) {
if (obj1.age == obj2.age) {
return NSOrderedSame;
}
else {
return obj1.age < obj2.age? NSOrderedAscending : NSOrderedDescending;
}
}];
for (CDPerson *tempPerson in sortedArray) {
NSLog(@"%@", tempPerson);
}
- Category與Extension
Category :類別相當于是我們給類打的一個補丁,通過這個補丁可以擴展類的能力呵俏。
Extension:匿名類別(類擴展)堆缘,通過匿名類別來聲明私有化的成員變量(也可以聲明在實現(xiàn)部分);前置聲明私有化的成員方法普碎;聲明私有化的屬性吼肥。 - 基本數(shù)據(jù)類型不能被添加到數(shù)組和字典等Objective-C 專有的數(shù)據(jù)結構中,也不能通過類別為其增強實現(xiàn)麻车。
- NSNumber 常用方法:
-xxxValue
- (NSNumber )initWithXxx:(xxx)value
+(NSNumber )numberWithXxx:(xxx)value
-(NSComparisonResult)compare:(NSNumber )aNumber
-(BOOL)isEqualToNumber:(NSNumber )aNumber
- NSValue是NSNumber的父類缀皱,可以存儲任何類型的數(shù)據(jù),包括符合數(shù)據(jù)類型(數(shù)組动猬,指針啤斗,結構體)甚至對象。
- NSTimeZone
+(NSTimeZone )systemTimeZone —-返回當前系統(tǒng)時區(qū)
+(NSTimeZone )systemTimeZone —-返回TimeZone支持時區(qū)的鍵值對
+(instancetype)timeZoneWithAbbreviation:(NSString *)abbreviation —- 通過傳入鍵值對的鍵赁咙,創(chuàng)建對應的時區(qū)對象钮莲。
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// 大寫的MM表示月??小寫的mm表示分鐘
// 大寫的SSS表示毫秒??小寫的ss表示秒
// 大寫的HH表示24小時制式的小時??小寫的hh表示12小時制式的小時 formatter.dateFormat = @"yyyy年MM月dd日 HH:mm:ss.SSS";
// GMT --- Greenwich Mean Time??格林尼治標準時間??
// +8 --- 東八區(qū)
formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT+8"];
NSLog(@"%@", [formatter stringFromDate:date]);
NSLog(@"%@", [formatter dateFromString:@"2008年08月08日 00:00:0 0.000"]);
- NULL
表示基礎類型指針為空
int *p = NULL;
nil:表示對象指針為空。
id obj = nil;
Nil :表示Class變量為空彼水。
Class class = Nil;
NSNull: 用在數(shù)組字典等數(shù)據(jù)結構中占位崔拥,作為空元素。
[NSNull null]; // 創(chuàng)建表示空的對象
- NSDateFormatter
NSDate *now = [NSDate date];
// NSDate對象的timeIntervalSinceDate:可以計算出兩個日期之間相差多少秒
int days = (int)lround([now timeIntervalSinceDate:_lendDate] / SECONDS_PER_DAY);
static NSDateFormatter *formatter = nil;
if (!formatter) {
formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd";
formatter.timeZone = [NSTimeZone systemTimeZone];
}
[formatter stringFromDate:_lendDate]凤覆;```
- NSRange
-(NSArray *) findBooksByName:(NSString *) name{
NSMutableArray *tempArray = [NSMutableArray array];
for (CDBook *tempBook in booksArray) {
// NSRange range = [temp.name rangeOfString:name];
// if(range.location != NSNotFound) {
//rangOfString:在一個字符串中查找是否含有另一個字符串
if([tempBook.name rangeOfString:name].location != NSNotFound){
[tempArray addObject:tempBook];
}
}
return [tempArray copy];
}```
- 數(shù)據(jù)持久化
將對數(shù)據(jù)結構轉換為NSData類對象的過程稱為歸檔(數(shù)據(jù)的序列化)链瓦;相反的過程稱之為解歸檔(數(shù)據(jù)的反序列化)。
#if 1
NSString *str = @"我愛你們";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[data writeToFile:@"/Users/Hao/Desktop/b.txt" atomically:NO];
#else
NSData *data = [NSData dataWithContentsOfFile:@"/Users/Hao/Des ktop/b.txt"];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);
#endif
}
#if 0
NSArray *array = @[@"apple", @"桔子", @"banana"];
// 創(chuàng)建數(shù)據(jù)中轉站
NSMutableData *mData = [NSMutableData data];
// 創(chuàng)建歸檔器
NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];
// 用鍵值對的方式進行歸檔(編碼)
[arch encodeObject:array forKey:@"abc"];
// 結束歸檔編碼
[arch finishEncoding];
// 將數(shù)據(jù)寫到硬盤文件上
[mData writeToFile:@"/Users/Hao/Desktop/foo" atomically:NO];
#else
// 創(chuàng)建一個數(shù)據(jù)中轉站將文件內容讀入中轉站
NSData *data = [NSData dataWithContentsOfFile:@"/Users/Hao/Desktop/foo"];
// 創(chuàng)建一個解歸檔器
NSKeyedUnarchiver *unarch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
// 通過鍵取出剛才存入的數(shù)據(jù)(解碼)
NSArray *array = [unarch decodeObjectForKey:@"abc"];
for (NSString *str in array) {
NSLog(@"%@", str);
}
#endif
任意對象的序列化和反序列化
@interface CDStudent : NSObject <NSCoding>
-(id) initWithCoder:(NSCoder *)aDecoder {
if(self = [super init]) {
if(aDecoder) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntForKey:@"age"];
} }
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInt:self.age forKey:@"age"];
}
#if 1
CDStudent *stu = [[CDStudent alloc] init];
stu.name = @"張三";
stu.age = 35;
NSMutableData *mData = [NSMutableData data];
NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritin gWithMutableData:mData];
[arch encodeObject:stu forKey:@"student"];
[arch finishEncoding];
[mData writeToFile:@"/Users/Hao/Desktop/bar" atomically:NO];
#else
NSData *data = [NSData dataWithContentsOfFile:@"/Users/Hao/Des ktop/bar"];
NSKeyedUnarchiver *unarch = [[NSKeyedUnarchiver alloc] initFor ReadingWithData:data];
CDStudent *stu = [unarch decodeObjectForKey:@"student"];
NSLog(@"%@", stu);
#endif
<u>如果對象中關聯(lián)了其他對象,如果在歸檔時要對關聯(lián)的對象進行歸檔
那么關聯(lián)的對象也必須遵循NSCoding協(xié)議才能進行歸檔
否則程序會崩潰</u>
plist文件
[mData writeToFile:FILENAME atomically:YES];
if ([[NSFileManager defaultManager] fileExistsAtPath:FILENAME]) {
NSData *data = [NSData dataWithContentsOfFile:FILENAME];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
booksArray = [unarchiver decodeObjectForKey:@"books"];
}
// 獲得默認的文件管理器對象
NSFileManager *manager = [NSFileManager defaultManager];
// 創(chuàng)建文件夾
// 如果第二個參數(shù)是YES則會在上級文件夾不存在時依次創(chuàng)建出上級文件夾再創(chuàng)建當前指定的文件夾
NSLog(@"%@", [manager createDirectoryAtPath:@"/Users/Hao/Desktop/abc/def/小狗屎" withIntermediateDirectories:YES attributes:nil error:nil]? @"創(chuàng)建文件夾成功": @"創(chuàng)建文件夾失敗");
- 協(xié)議的作用和語法:協(xié)議是一組方法的集合盯桦,協(xié)議中只有方法的聲明沒有方法的實現(xiàn)慈俯,這些方法是留給該協(xié)議的類做出多態(tài)實現(xiàn)的方法。協(xié)議表示約定拥峦、能力贴膘、角色。
id<Flyable> bird = [[Bird alloc] init];
id<Flyable> superman = [[Superman alloc] init];
id<Flyable> airplane = [[Airplane alloc] init];
NSArray *array = @[bird, superman, airplane];
for (id<Flyable> temp in array) {
[temp fly];
} ```
// 多態(tài): 同樣的指針調用相同的方法做了不同的事情
// 不同的類遵循相同的協(xié)議并對協(xié)議中的方法給出不同的實現(xiàn)版本
for (id<CDFlyable> temp in array) {
// 在運行時判定指針指向的對象是否遵循協(xié)議
if ([temp conformsToProtocol:@protocol(CDFlyable)]) {
[temp fly];
}
}```
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *comps = [cal components:NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:[NSDate date]];
//return [self initWithHour:comps.hour minute:comps.minute second:comps.second];
if (_delegate && [_delegate conformsToProtocol:@protocol(CDPowerProviderProtocol)]) {
[_delegate providePower];
NSLog(@"電機啟動可以刮胡子了...");
}```
- 代理模式:代理對象代理被代理對象的行為略号,代理對象可以通過被代理對象的指針執(zhí)行被代理對象的行為步鉴,與此同時代理對象可以對這些行為進行
委托回調:回調是一種常用的編程模式揪胃,它通常通過設置委托來實現(xiàn)。委托方做不了的事情讓被委托方做氛琢,被委托方必須遵循某種協(xié)議喊递,委托方要持有一個指向該對象的指針。
/*槍手/
@interface Gunman : NSObject <CandidateProtocol>
@property (nonatomic, copy) NSString *name;
// 代理對象中要有一個指向被代理對象的指針
// 通過這個指針代理對象可以調用被代理對象的方法
@property (nonatomic, weak) id<CandidateProtocol> target; ```
-(instancetype)initWithName:(NSString *)name target:(id<CDCandidate>)target {
if (self = [super init]) {
_name = name;
_target = target;
}
return self;
}
-(void) doExam {
// 執(zhí)行被代理對象的行為
[_target doExam];
// 增強實現(xiàn)
NSLog(@"奮筆疾書正確答案");
NSLog(@"交卷");
}
// 總結: 委托回調的編程模式可以幫助程序實現(xiàn)解耦合
委托方定義一個指針(id<CDCandidate>delegate)指向被委托方阳似,在被委托方中綁定委托骚勘,遵循協(xié)議即可。
// 定義一個指針指向被委托方
// 當遇到知道什么時候做某事但不知道怎么做的場景
// 都可以使用委托回調的編程模式來實現(xiàn)代碼的解耦合
// 創(chuàng)建一個鬧鐘對象
AlarmClock *ac = [[AlarmClock alloc] init];
// 告訴鬧鐘待會你要喚醒的對象是誰
// 委托方是鬧鐘??被委托方是人
// 人被喚醒這件事情要委托給人來執(zhí)行
// 因為人遵循Awakable協(xié)議實現(xiàn)了beAwaken方法
ac.delegate = self;
// 調用鬧鐘的方法設定多少秒之后響鬧鐘
[ac alarmAfter:seconds];
NSDate *date = [NSDate date];
// 創(chuàng)建一個日歷對象
NSCalendar *cal = [NSCalendar currentCalendar];
// 創(chuàng)建一個日期成員對象
NSUInteger flag = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *comp = [cal components:flag fromDate:date];
self.hour = (int)[comp hour];
self.minute = (int)[comp minute];
self.second = (int)[comp second];
/**鬧鐘??繼承了Clock除了走字和顯示時間還要提供定時鬧鈴的功能??*/ ```
@interface AlarmClock : Clock
// 通過delegate屬性設置被委托方
// 被委托的對象是一個遵循Awakable協(xié)議的對象
// 所以delegate屬性的類型是一個指向Awakable對象的指針
@property (nonatomic, weak) id<Awakable> delegate;
/*在指定時間之后響鬧鐘/
-(void) alarmAfter:(int) seconds;
// 通過指向被委托方的指針調用被委托方的回調方法??人被喚醒??
// 將self作為參數(shù)傳入beAwaken方法這樣人可以通過時鐘對象
// 獲得現(xiàn)在時鐘上顯示的時間??實現(xiàn)了數(shù)據(jù)的反向傳遞??
[self.delegate beAwaken:self]; ```
@interface CDUtility : NSObject
+(void) saveData:(NSData *) data withDataHandler:(id<CDStroageProtocol>) handler;
@end
+(void) saveData:(NSData *)data withDataHandler:(id<CDStroageProtocol>)handler {
if (handler && [handler conformsToProtocol:@protocol(CDStroageProtocol)]) {
[handler store:data];
}
}
NSData *data = [NSData dataWithContentsOfFile:@"/Users/Hao/Desktop/girl.json"];
[CDUtility saveData:data withDataHandler:[[CDRemovableStorage alloc] init]];
- JSON解析
NSData *data = [NSData dataWithContentsOfFile:@"/Users/alvin/Desktop/girl.json"];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:1 error:nil];
NSArray *items = dict[@"items"];
[items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *str = obj[@"wpic_large"];
// printf("第%ld條: %s\n", idx + 1, str.UTF8String);
NSData *pic = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];
// NSLog(@"%@", [manager createFileAtPath:@"/Users/chengduqianfeng/Desktop/abc" contents:pic attributes:nil]? @"創(chuàng)建成功":@"創(chuàng)建失敗"); NSLog(@"%@",[pic writeToFile:@"/Users/alvin/Desktop/abc" atomically:YES]?@"創(chuàng)建成功":@"創(chuàng)建失敗");
}];```
NSURL *url = [NSURL URLWithString:@"http://223.6.252.214/we
ibofun/weibo_list.php?apiver=10500&category=weibo_jokes&page=0&page
_size=30&max_timestamp=-1"];
// 通過該URL以同步方式獲取數(shù)據(jù)
NSData *data = [NSData dataWithContentsOfURL:url];
// 將收到的JSON格式的數(shù)據(jù)處理成字典對象
NSDictionary *dict = [NSJSONSerialization JSONObjectWithDat
a:data options:0 error:nil];
// 取出字典中的items鍵對應的數(shù)組
NSArray *array = dict[@"items"]; ```
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
[dictionary setValue:@"xiaominfc" forKey:@"username"];
[dictionary setValue:@"1991-03-26" forKey:@"birthday"];
[dictionary setValue:[NSNumber numberWithInteger:23] forKey:@"age"];
NSArray *arrayOfAnthonysChildren = [[NSArray alloc]initWithObjects:@"Java",@"Objective-C",@"Python",@"C++", nil];
[dictionary setValue:arrayOfAnthonysChildren forKey:@"program_language"];
if([NSJSONSerialization isValidJSONObject:dictionary]){
NSLog(@"it is a JSONObject!");
}
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error];
if([jsonData length] > 0 && error == nil) {
NSString *jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"data:%@",jsonString);
}```
-(void) setValue:(id)value forKey:(NSString *)key {
// 對于屬性和JSON數(shù)據(jù)類型不匹配的情況需要手動轉換
if ([key isEqualToString:@"wid"]) {
self.wid = [value integerValue];
}
else if ([key isEqualToString:@"comments"]) {
self.comments = [value integerValue];
}
else if ([key isEqualToString:@"likes"]) {
self.likes = [value doubleValue];
}
else if ([key isEqualToString:@"updateTime"]) {
self.updateTime = [NSDate dateWithTimeIntervalSince1970:[value integerValue]];//將讀取的json中的格林威治時間字符串轉換為標準時間撮奏。
}
else {
// 對于不需要類型轉換的鍵值對組合直接使用KVC賦值
[super setValue:value forKey:key];
// 不能寫下面的代碼否則會因為遞歸調用不收斂導致棧溢出
// [self setValue:value forKey:key];
}
}```
// 提示: 使用KVC大招時一定重寫此方法
-(void)setValue:(id)value forUndefinedKey:(NSString *)key {
// 在使用KVC時通常都需要重寫此方法來處理不能識別的key
// 如果JSON數(shù)據(jù)中的鍵和類的屬性名不匹配可以通過下面的字典進行轉換
NSDictionary *keyPropDict = @{@"wpic_large": @"largePicUrl", @"update_time": @"updateTime"};
// 如果JSON中的鍵在類中有與之對應的屬性才使用KVC給該屬性賦值
// 如果沒有對應的屬性就什么都不要做
if (keyPropDict[key]) {
[self setValue:value forKey:keyPropDict[key]];
}
}```
static const NSString *PATH = @"/Users/alvin/Desktop";
// 保存圖片以及圖片描述
void foo(NSArray * array) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *path = [PATH stringByAppendingPathComponent:@"美女圖片"];
if (![fileManager fileExistsAtPath:path]) {
[fileManager createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:nil];
}
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
CDGirlPhoto *girl = obj;
NSLog(@"%@", girl.updateTime);
NSString *urlStr = girl.largePicUrl;
NSString *filename = [[PATH stringByAppendingPathComponent:@"美女圖片"] stringByAppendingPathComponent:[urlStr lastPathComponent]];
[[NSData dataWithContentsOfURL:[NSURL URLWithString:urlStr]] writeToFile:filename atomically:YES];
NSString *txtFilename = [[filename substringToIndex:[filename rangeOfString:@"." options:NSBackwardsSearch].location + 1] stringByAppendingString:@"txt"];
[girl.wbody writeToFile:txtFilename atomically:YES encoding:NSUTF8StringEncoding error:nil];
}];
}```
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSData *data = [NSData dataWithContentsOfFile:[PATH stringByAppendingPathComponent:@"girl.json"]];
// 將JSON格式的數(shù)據(jù)轉換成字典
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:1 error:nil];
// 通過索引器語法取出items鍵對應的數(shù)組
NSArray *array = dict[@"items"];
NSMutableArray *girls = [NSMutableArray array];
for (NSDictionary *objDict in array) {
// 有一個字典就創(chuàng)建一個與之對應的模型對象
CDGirlPhoto *girl = [[CDGirlPhoto alloc] init];
// 通過KVC(Key Value Coding)方式給對象的屬性賦值
[girl setValuesForKeysWithDictionary:objDict];
// 將模型對象添加到數(shù)組中保存和管理起來
[girls addObject:girl];
}
foo(girls);
}
return 0;
}```
- 解析XML數(shù)據(jù)文件
- SAX --- 順序解析 事件驅動(遇到標簽俏讹、屬性、內容都會引發(fā)相應的事件執(zhí)行事件回調來處理XML文件中的數(shù)據(jù))
- DOM (Document Object Model) --- 支持XPath查找畜吊,可以動態(tài)的增加刪除修改節(jié)點泽疆,占用內存較多
NSURL *url = [NSURL URLWithString:@"http://www.oschina.net/action/api/news_detail?id=44393"];
NSData *data = [NSData dataWithContentsOfURL:url];
// 使用NSData對象創(chuàng)建XML文檔對象
// 文檔對象是將XML在內存中組織成一棵樹
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
// 使用XPath語法從文檔對象模型中查找指定節(jié)點
NSArray *array = [doc nodesForXPath:@"http://relative" error:nil
// 循環(huán)取出節(jié)點并對節(jié)點下的子節(jié)點進行進一步解析
for (GDataXMLNode *node in array) {
// 取出子節(jié)點的字符換值
NSString *title = [[node nodesForXPath:@"rtitle" error:nil][0] stringValue];
NSString *url = [[node nodesForXPath:@"rurl" error:nil][0] stringValue];
printf("標題??%s\n鏈接地址??%s\n\n", title.UTF8String, url .UTF8String);
} ```
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.oschina.net/action/api/news_detail?id=44393"]];
// 根據(jù)獲得的XML數(shù)據(jù)創(chuàng)建文檔對象(DOM)
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
NSArray *array = [doc nodesForXPath:@"http://title" error:nil];
NSLog(@"%@", [[array firstObject] stringValue]);
array = [doc nodesForXPath:@"http://relative" error:nil];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
GDataXMLNode *node = obj;
NSLog(@"標題: %@", [[node.children firstObject] stringValue]);
NSLog(@"鏈接: %@", [[node.children lastObject] stringValue]);
}];```
- **block**
As a property:
`@property (nonatomic,copy) returnType (^blockName)(parameterTypes);`
As a method parameter:
`-(void)someMethodThatTakesABlock:(returnType (^(parameterTypes))blockName;`
+(void)saveData:(NSData *)data withDataHandler:(void (^)(NSData *))dataHandler {
dataHandler(data); } ```
As an argument to a method call:
[someObject someMethodThatTakesABlock:^retuenType (parameters){…}];
[CDMyUtil saveData:data withDataHandler:^(NSData * myData) {
[myData writeToFile:@"" atomically:NO];
}];```
As a typedef:
`typedef returnType (^TypeName)(parameterTypes);`
typedef void (^CDDataHandlerBlockType)(NSData *);
TypeName blockName =^returnType(parameters){…};```
// 聲明Block變量
int (^sum)(int, int);
// 定義一個Block并賦值給變量
sum sum=^int(int a,int b){return a+b;};
// 調用Block
printf("%d\n", sum(1, 2));
+(int (^)(int, int)) foo {
int a=1;
// 在Block中變量a是只讀的
// 如果想修改它需要用__block修飾
return ^ int (int b, int c) {
return a+b+c; };
} ```