你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> IOS開發系列—Objective-C之Foundation框架

IOS開發系列—Objective-C之Foundation框架

編輯:IOS開發綜合
概述 我們前面的章節中就一直新建Cocoa Class,那麼Cocoa到底是什麼,它和我們前面以及後面要講的內容到底有什麼關系呢?Objective-C開發中經常用到NSObject,那麼這個對象到底是誰?它為什麼又出現在Objective-C中間呢?今天我們將揭開這層面紗,重點分析在IOS開發中一個重要的框架Foundation,今天的主要內容有:     為什麼前面說的內容中新建一個類的時候我們都是選擇Cocoa Class呢?Cocoa是什麼呢?   Cocoa不是一種編程語言(它可以運行多種編程語言),它也不是一個開發工具(通過命令行我們仍然可以開發Cocoa程序),它是創建Mac OS X和IOS程序的原生面向對象API,為這兩者應用提供了編程環境。   我們通常稱為“Cocoa框架”,事實上Cocoa本身是一個框架的集合,它包含了眾多子框架,其中最重要的要數“Foundation”和“UIKit”。前者是框架的基礎,和界面無關,其中包含了大量常用的API;後者是基礎的UI類庫,以後我們在IOS開發中會經常用到。這兩個框架在系統中的位置如下圖:   Cocoa   其實所有的Mac OS X和IOS程序都是由大量的對象構成,而這些對象的根對象都是NSObject,NSObject就處在Foundation框架之中,    通常我們會將他們分為幾類:   值對象 集合 操作系統服務:文件系統、URL、進程通訊 通知 歸檔和序列化 表達式和條件判斷 Objective-C語言服務 UIKit主要用於界面構架,這裡我們不妨也看一下它的類結構:   UIKit   常用結構體 在Foundation中定義了很多常用結構體類型來簡化我們的日常開發,這些結構體完全采用Objective-C定義,和我們自己定義的結構體沒有任何區別,之所以由框架為我們提供完全是為了簡化我們的開發。常用的結構體有NSRange、NSPoint、NSSize、NSRect等   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>   /*NSRange表示一個范圍*/ void test1(){     NSRange rg={3,5};//第一參數是起始位置第二個參數是長度     //NSRange rg;     //rg.location=3;     //rg.length=5;     //NSRange rg={.location=3,.length=5};     //常用下面的方式定義 NSRange rg2=NSMakeRange(3,5);//使用NSMakeRange定義一個NSRange      //打印NSRange可以使用Foundation中方法 NSLog(@"rg2 is %@", NSStringFromRange(rg2));//注意不能直接NSLog(@"rg2 is %@", rg2),因為rg2不是對象(准確的說%@是指針)而是結構體 } /*NSPoint表示一個點*/ void test2(){     NSPoint p=NSMakePoint(10, 15);//NSPoint其實就是CGPoint     //這種方式比較常見 NSPoint p2=CGPointMake(10, 15);     NSLog(NSStringFromPoint(p2)); } /*NSSize表示大小*/ void test3(){     NSSize s=NSMakeSize(10, 15);//NSSize其實就是CGSize     //這種方式比較常見 CGSize s2=CGSizeMake(10, 15);     NSLog(NSStringFromSize(s2)); } /*NSRect表示一個矩形*/ void test4(){     NSRect r=NSMakeRect(10, 5, 100, 200);//NSRect其實就是CGRect     //這種方式比較常見 NSRect r2=CGRectMake(10, 5, 100, 200);     NSLog(NSStringFromRect(r2)); }   int main(int argc, const char * argv[]) {     @autoreleasepool {         test1();         test2();         test3();         test4();     } return 0; } 可以看到對於常用結構體在Foundation框架中都有一個對應的make方法進行創建,這也是我們日後比較常用的操作;而且與之對應的還都有一個NSStringFromXX方法來進行字符串轉換,方便我們調試。上面也提到NSSize其實就是CGSize,NSRect其實就是CGRect,我們可以通過查看代碼進行確認,例如NSSize定義: NSSize   繼續查看CGSize的代碼:   CGSize   日期 接下來熟悉一下Foundation框架中日期的操作   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>     int main(int argc, const char * argv[]) {          NSDate *date1=[NSDate date];//獲得當前日期     NSLog(@"%@",date1); //結果:2014-07-16 07:25:28 +0000          NSDate *date2=[NSDate dateWithTimeIntervalSinceNow:100];//在當前日期的基礎上加上100秒,注意在ObjC中多數時間單位都是秒     NSLog(@"%@",date2); //結果:2014-07-16 07:27:08 +0000          NSDate *date3=[NSDate distantFuture];//隨機獲取一個將來的日期     NSLog(@"%@",date3); //結果:4001-01-01 00:00:00 +0000          NSTimeInterval time=[date2 timeIntervalSinceDate:date1];//日期之差,返回單位為秒     NSLog(@"%f",time); //結果:100.008833          NSDate *date5=[date1 earlierDate:date3];//返回比較早的日期     NSLog(@"%@",date5); //結果:2014-07-16 07:25:28 +0000          //日期格式化     NSDateFormatter *formater1=[[NSDateFormatter alloc]init];     formater1.dateFormat=@"yy-MM-dd HH:mm:ss";     NSString *datestr1=[formater1 stringFromDate:date1];     NSLog(@"%@",datestr1); //結果:14-07-16 15:25:28     //字符串轉化為日期     NSDate *date6=[formater1 dateFromString:@"14-02-14 11:07:16"];     NSLog(@"%@",date6); //結果:2014-02-14 03:07:16 +0000       return 0; } 字符串 不可變字符串   在ObjC中字符串操作要比在C語言中簡單的多,在下面的例子中你將看到字符串的初始化、大小寫轉化、後綴前綴判斷、字符串比較、字符串截取、字符串轉換等,通過下面的例子我們基本可以掌握常用的字符串操作(注意這些內容雖然基本,但卻是十分常用的操作,需要牢記):   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>     /**字符串操作*/ void test1(){     char *str1="C string";//這是C語言創建的字符串     NSString *str2=@"OC string";//ObjC字符串需要加@,並且這種方式創建的對象不需要自己釋放內存       //下面的創建方法都應該釋放內存     NSString *str3=[[NSString alloc] init];     str3=@"OC string";     NSString *str4=[[NSString alloc] initWithString:@"Objective-C string"];     NSString *str5=[[NSString alloc] initWithFormat:@"age is %i,name is %.2f",19,1.72f];     NSString *str6=[[NSString alloc] initWithUTF8String:"C string"];//C語言的字符串轉換為ObjC字符串       //以上方法都有對應靜態方法(一般以string開頭),不需要管理內存(系統靜態方法一般都是自動釋放)     NSString *str7=[NSString stringWithString:@"Objective-C string"]; } void test2(){     NSLog(@"\"Hello world!\" to upper is %@",[@"Hello world!" uppercaseString]);     //結果:"Hello world!" to upper is HELLO WORLD!     NSLog(@"\"Hello world!\" to lowwer is %@",[@"Hello world!" lowercaseString]);     //結果:"Hello world!" to lowwer is hello world!           //首字母大寫,其他字母小寫     NSLog(@"\"Hello world!\" to capitalize is %@",[@"Hello world!" capitalizedString]);     //結果:"Hello world!" to capitalize is Hello World!           BOOL result= [@"abc" isEqualToString:@"aBc"];     NSLog(@"%i",result);     //結果:0     NSComparisonResult result2= [@"abc" compare:@"aBc"];//如果是[@"abc" caseInsensitiveCompare:@"aBc"]則忽略大小寫比較     if(result2==NSOrderedAscending){         NSLog(@"left<right.");     }else if(result2==NSOrderedDescending){         NSLog(@"left>right.");     }else if(result2==NSOrderedSame){         NSLog(@"left=right.");     }     //結果:left>right. } void test3(){     NSLog(@"has prefix ab? %i",[@"abcdef" hasPrefix:@"ab"]);     //結果:has prefix ab? 1     NSLog(@"has suffix ab? %i",[@"abcdef" hasSuffix:@"ef"]);     //結果:has suffix ab? 1     NSRange range=[@"abcdefabcdef" rangeOfString:@"cde"];//注意如果遇到cde則不再往後面搜索,如果從後面搜索或其他搜索方式可以設置第二個options參數     if(range.location==NSNotFound){         NSLog(@"not found.");     }else{         NSLog(@"range is %@",NSStringFromRange(range));     }     //結果:range is {2, 3} } //字符串分割 void test4(){     NSLog(@"%@",[@"abcdef" substringFromIndex:3]);//從第三個索引開始(包括第三個索引對應的字符)截取到最後一位     //結果:def     NSLog(@"%@",[@"abcdef" substringToIndex:3]);////從0開始截取到第三個索引(不包括第三個索引對應的字符)     //結果:abc     NSLog(@"%@",[@"abcdef" substringWithRange:NSMakeRange(2, 3)]);     //結果:cde     NSString *str1=@"12.abcd.3a";     NSArray *array1=[str1 componentsSeparatedByString:@"."];//字符串分割     NSLog(@"%@",array1);      /*結果:       (          12,          abcd,          3a       )       */   } //其他操作 void test5(){     NSLog(@"%i",[@"12" intValue]);//類型轉換     //結果:12     NSLog(@"%zi",[@"hello world,世界你好!" length]);//字符串長度注意不是字節數     //結果:17     NSLog(@"%c",[@"abc" characterAtIndex:0]);//取出制定位置的字符     //結果:a     const char *s=[@"abc" UTF8String];//轉換為C語言字符串     NSLog(@"%s",s);     //結果:abc }   int main(int argc, const char * argv[]) {     test1();     test2();     test3();     test4();     test5();     return 0; } 擴展--文件操作   在ObjC中路徑、文件讀寫等操作是利用字符串來完成的,這裡通過幾個簡單的例子來演示(首先在桌面上新建一個test.txt文件,裡面存儲的內容是”hello world,世界你好!”)   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>     void test1(){     //讀取文件內容     NSString *path=@"/Users/kenshincui/Desktop/test.txt";     NSString *str1=[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];     //注意上面也可以使用gb2312 gbk等,例如kCFStringEncodingGB_18030_2000,但是需要用CFStringConvertEncodingToNSStringEncoding轉換     NSLog(@"str1 is %@",str1);     //結果:str1 is hello world,世界你好!                      //上面我們看到了讀取文件,但並沒有處理錯誤,當然在ObjC中可以@try @catch @finnally但通常我們並不那麼做     //由於我們的test.txt中有中文,所以使用下面的編碼讀取會報錯,下面的代碼演示了錯誤獲取的過程     NSError *error;     NSString *str2=[NSString stringWithContentsOfFile:path encoding:kCFStringEncodingGB_18030_2000 error:&error];//注意這句話中的error變量是**error,就是指針的指針那就是指針的地址,由於error就是一個指針此處也就是error的地址&error,具體原因見下面補充     if(error){         NSLog(@"read error ,the error is %@",error);     }else{         NSLog(@"read success,the file content is %@",str2);     }     //結果:read error ,the error is Error Domain=NSCocoaErrorDomain Code=261 "The file couldn’t be opened using the specified text encoding." UserInfo=0x100109620 {NSFilePath=/Users/kenshincui/Desktop/test.txt, NSStringEncoding=1586}                      //讀取文件內容還有一種方式就是利用URl,它除了可以讀取本地文件還可以讀取網絡文件     //NSURL *url=[NSURL URLWithString:@"file:///Users/kenshincui/Desktop/test.txt"];     NSURL *url=[NSURL URLWithString:@"http://www.apple.com"];     NSString *str3=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];     NSLog(@"str3 is %@",str3); } void test2(){     //下面是文件寫入     NSString *path1=@"/Users/kenshincui/Desktop/test2.txt";     NSError *error1;     NSString *str11=@"hello world,世界你好!";     [str11 writeToFile:path1 atomically:YES encoding:NSUTF8StringEncoding error:&error1];//automically代表一次性寫入,如果寫到中間出錯了最後就全部不寫入     if(error1){         NSLog(@"write fail,the error is %@",[error1 localizedDescription]);//調用localizedDescription是只打印關鍵錯誤信息     }else{         NSLog(@"write success!");     }     //結果:write success! } //路徑操作 void test3(){     NSMutableArray *marray=[NSMutableArray array];//可變數組     [marray addObject:@"Users"];     [marray addObject:@"KenshinCui"];     [marray addObject:@"Desktop"];       NSString *path=[NSString pathWithComponents:marray];     NSLog(@"%@",path);//字符串拼接成路徑     //結果:Users/KenshinCui/Desktop       NSLog(@"%@",[path pathComponents]);//路徑分割成數組     /*結果:       (         Users,         KenshinCui,         Desktop     )     */       NSLog(@"%i",[path isAbsolutePath]);//是否覺對路徑(其實就是看字符串是否以“/”開頭)     //結果:0     NSLog(@"%@",[path lastPathComponent]);//取得最後一個目錄     //結果:Desktop     NSLog(@"%@",[path stringByDeletingLastPathComponent]);//刪除最後一個目錄,注意path本身是常量不會被修改,只是返回一個新字符串     //結果:Users/KenshinCui     NSLog(@"%@",[path stringByAppendingPathComponent:@"Documents"]);//路徑拼接     //結果:Users/KenshinCui/Desktop/Documents }  //擴展名操作 void test4(){     NSString *path=@"Users/KenshinCui/Desktop/test.txt";     NSLog(@"%@",[path pathExtension]);//取得擴展名,注意ObjC中擴展名不包括"."     //結果:txt     NSLog(@"%@",[path stringByDeletingPathExtension]);//刪除擴展名,注意包含"."     //結果:Users/KenshinCui/Desktop/test     NSLog(@"%@",[@"Users/KenshinCui/Desktop/test" stringByAppendingPathExtension:@"mp3"]);//添加擴展名     //結果:Users/KenshinCui/Desktop/test.mp3 }   int main(int argc, const char * argv[]) {     test1();     test2();     test3();     test4();     return 0; } 注意:在上面的例子中我們用到了可變數組,下面會專門介紹。   可變字符串   我們知道在字符串操作過程中我們經常希望改變原來的字符串,當然這在C語言中實現比較復雜,但是ObjC為我們提供了新的可變字符串類NSMutableString,它是NSString的子類。   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>     int main(int argc, const char * argv[]) {          /*可變字符串,注意NSMutableString是NSString子類*/     //注意雖然initWithCapacity分配字符串大小,但是不是絕對的不可以超過此范圍,聲明此變量對性能有好處     NSMutableString *str1= [[NSMutableString alloc] initWithCapacity:10];     [str1 setString:@"hello"];//設置字符串     NSLog(@"%@",str1);     //結果:hello       [str1 appendString:@",world!"];//追加字符串     NSLog(@"%@",str1);     //結果:hello,world!       [str1 appendFormat:@"我的年齡是%i。dear,I love you.",18];     NSLog(@"%@",str1);     //結果:hello,world!我的年齡是18。dear,I love you.          //替換字符串     NSRange range=[str1 rangeOfString:@"dear"];     [str1 replaceCharactersInRange:range withString:@"Honey"];     NSLog(@"%@",str1);     //結果:hello,world!我的年齡是18。Honey,I love you.          //插入字符串     [str1 insertString:@"My name is Kenshin." atIndex:12];     NSLog(@"%@",str1);     //結果:hello,world!My name is Kenshin.我的年齡是18。Honey,I love you.          //刪除指定字符串     [str1 deleteCharactersInRange:[str1 rangeOfString:@"My name is Kenshin."]];//刪除指定范圍的字符串     NSLog(@"%@",str1);     //結果:hello,world!我的年齡是18。Honey,I love you.          return 0; } 數組 不可變數組   下面將演示常用的數組操作:初始化、數組對象的方法執行、數組元素的遍歷、在原有數組基礎上產生新數組、數組排序等   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h> #import "Person.h"     void test1(){     //NSArray長度不可變所以初始化的時候就賦值,並且最後以nil結尾     //此外需要注意NSArray不能存放C語言的基礎類型     NSObject *obj=[[NSObject alloc]init];     //NSArray *array1=[[NSArray alloc] initWithObjects:@"abc",obj,@"cde",@"opq", nil];     NSArray *array1=[NSArray arrayWithObjects:@"abc",obj,@"cde",@"opq",@25, nil];     NSLog(@"%zi",array1.count);//數組長度,結果:5     NSLog(@"%i",[array1 containsObject:@"cde"]);//是否包含某個對象,結果:1     NSLog(@"%@",[array1 lastObject]);//最後一個對象,結果:25     NSLog(@"%zi",[array1 indexOfObject:@"abc"]);//對象所在的位置:0          Person *person1=[Person personWithName:@"Kenshin"];     Person *person2=[Person personWithName:@"Kaoru"];     Person *person3=[Person personWithName:@"Rosa"];     NSArray *array2=[[NSArray alloc]initWithObjects:person1,person2,person3, nil];     [array2 makeObjectsPerformSelector:@selector(showMessage:) withObject:@"Hello,world!"];//執行所有元素的showMessage方法,後面的參數最多只能有一個     /*結果:      My name is Kenshin,the infomation is "Hello,world!".      My name is Kaoru,the infomation is "Hello,world!".      My name is Rosa,the infomation is "Hello,world!".      */ } //數組的遍歷 void test2(){     NSObject *obj=[[NSObject alloc]init];     NSArray *array=[[NSArray alloc] initWithObjects:@"abc",obj,@"cde",@"opq",@25, nil];     //方法1     for(int i=0,len=array.count;i<len;++i){         NSLog(@"method1:index %i is %@",i,[array objectAtIndex:i]);     }     /*結果:      method1:index 0 is abc      method1:index 1 is <NSObject: 0x100106de0>      method1:index 2 is cde      method1:index 3 is opq      method1:index 4 is 25      */               //方法2     for(id obj in array){         NSLog(@"method2:index %zi is %@",[array indexOfObject:obj],obj);     }     /*結果:      method2:index 0 is abc      method2:index 1 is <NSObject: 0x100602f00>      method2:index 2 is cde      method2:index 3 is opq      method2:index 4 is 25      */               //方法3,利用代碼塊方法     [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {         NSLog(@"method3:index %zi is %@",idx,obj);         if(idx==2){//當idx=2時設置*stop為YES停止遍歷             *stop=YES;         }     }];     /*結果:      method3:index 0 is abc      method3:index 1 is <NSObject: 0x100106de0>      method3:index 2 is cde      */               //方法4,利用迭代器     //NSEnumerator *enumerator= [array objectEnumerator];//獲得一個迭代器     NSEnumerator *enumerator=[array reverseObjectEnumerator];//獲取一個反向迭代器     //NSLog(@"all:%@",[enumerator allObjects]);//獲取所有迭代對象,注意調用完此方法迭代器就遍歷完了,下面的nextObject就沒有值了     id obj2=nil;     while (obj2=[enumerator nextObject]) {         NSLog(@"method4:%@",obj2);     }     /*結果:      method4:25      method4:opq      method4:cde      method4:<NSObject: 0x100106de0>      method4:abc      */ } //數組派生出新的數組 void test3(){     NSArray *array=[NSArray arrayWithObjects:@"1",@"2",@"3", nil];     NSArray *array2=[array arrayByAddingObject:@"4"];//注意此時array並沒有變     NSLog(@"%@",array2);     /*結果:      (          1,          2,          3,          4      )      */               NSLog(@"%@",[array2 arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"5",@"6", nil]]);//追加形成新的數組     /*結果:      (          1,          2,          3,          4,          5,          6      )      */               NSLog(@"%@",[array2 subarrayWithRange:NSMakeRange(1, 3)]);//根據一定范圍取得生成一個新的數組     /*結果:      (          2,          3,          4      )      */               NSLog(@"%@",[array componentsJoinedByString:@","]);//數組連接,形成一個字符串     //結果:1,2,3          //讀寫文件     NSString *path=@"/Users/KenshinCui/Desktop/array.xml";     [array writeToFile:path atomically:YES];     NSArray *array3=[NSArray arrayWithContentsOfFile:path];     NSLog(@"%@",array3);     /*結果:      (          1,          2,          3      )      */ } //數組排序 void test4(){     //方法1,使用自帶的比較器     NSArray *array=[NSArray arrayWithObjects:@"3",@"1",@"2", nil];     NSArray *array2= [array sortedArrayUsingSelector:@selector(compare:)];     NSLog(@"%@",array2);     /*結果:      (          1,          2,          3      )      */               //方法2,自己定義比較器     Person *person1=[Person personWithName:@"Kenshin"];     Person *person2=[Person personWithName:@"Kaoru"];     Person *person3=[Person personWithName:@"Rosa"];     NSArray *array3=[NSArray arrayWithObjects:person1,person2,person3, nil];     NSArray *array4=[array3 sortedArrayUsingSelector:@selector(comparePerson:)];     NSLog(@"%@",array4);     /*結果:      (          "name=Kaoru",          "name=Kenshin",          "name=Rosa"      )      */               //方法3使用代碼塊     NSArray *array5=[array3 sortedArrayUsingComparator:^NSComparisonResult(Person *obj1, Person *obj2) {         return [obj2.name compare:obj1.name];//降序     }];     NSLog(@"%@",array5);     /*結果:      (          "name=Rosa",          "name=Kenshin",          "name=Kaoru"      )      */               //方法4 通過描述器定義排序規則     Person *person4=[Person personWithName:@"Jack"];     Person *person5=[Person personWithName:@"Jerry"];     Person *person6=[Person personWithName:@"Tom"];     Person *person7=[Person personWithName:@"Terry"];     NSArray *array6=[NSArray arrayWithObjects:person4,person5,person6,person7, nil];     //定義一個排序描述     NSSortDescriptor *personName=[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];     NSSortDescriptor *accountBalance=[NSSortDescriptor sortDescriptorWithKey:@"account.balance" ascending:YES];     NSArray *des=[NSArray arrayWithObjects:personName,accountBalance, nil];//先按照person的name排序再按照account的balance排序     NSArray *array7=[array6 sortedArrayUsingDescriptors:des];     NSLog(@"%@",array7);     /*結果:      (          "name=Jack",          "name=Jerry",          "name=Terry",          "name=Tom"      )      */ }   int main(int argc, const char * argv[]) {     test1();     test2();     test3();     test4();     return 0; } 需要注意幾點:   NSArray中只能存放對象,不能存放基本數據類型,通常我們可以通過在基本數據類型前加@進行轉換; 數組中的元素後面必須加nil以表示數據結束; makeObjectsPerformSelector執行數組中對象的方法,其參數最多只能有一個; 上面數組操作中無論是數組的追加、刪除、截取都沒有改變原來的數組,只是產生了新的數組而已; 對象的比較除了使用系統自帶的方法,我們可以通過自定義比較器的方法來實現; 可變數組   下面看一下可變數組的內容:   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h> #import "Person.h"     void test1(){     Person *person1=[Person personWithName:@"Kenshin"];     Person *person2=[Person personWithName:@"Kaoru"];     Person *person3=[Person personWithName:@"Rosa"];     NSMutableArray *array1=[NSMutableArray arrayWithObjects:person1,person2,person3, nil];     NSLog(@"%@",array1);     /*結果:      (          "name=Kenshin",          "name=Kaoru",          "name=Rosa"      )      */          Person *person4=[Person personWithName:@"Jack"];//此時person4的retainCount為1     [array1 addObject:person4];//添加一個元素,此時person4的retainCount為2     NSLog(@"%@",array1);     /*結果:      (          "name=Kenshin",          "name=Kaoru",          "name=Rosa",          "name=Jack"      )      */          [array1 removeObject:person3];//刪除一個元素     NSLog(@"%@",array1);     /*結果:      (          "name=Kenshin",          "name=Kaoru",          "name=Jack"      )      */          [array1 removeLastObject];//刪除最後一個元素,//此時person4的retainCount為1     NSLog(@"%@",array1);     /*結果:      (          "name=Kenshin",          "name=Kaoru"      )      */          [array1 removeAllObjects];//刪除所以元素          //注意當往數組中添加一個元素時會retain因此計數器+1,當從數組中移除一個元素時會release因此計數器-1     //當NSMutalbeArray對象release的時候會依次調用每一個對象的release } void test2(){     NSMutableArray *array1=[NSMutableArray arrayWithObjects:@"1",@"3",@"2", nil];     NSLog(@"%@",array1);     /*結果:      (          1,          3,          2      )      */          NSArray *array2= [array1 sortedArrayUsingSelector:@selector(compare:)];//注意這個方法沒有修改array1     NSLog(@"%@",array1);     /*結果:      (          1,          3,          2      )      */          NSLog(@"%@",array2);     /*結果:      (          1,          2,          3      )      */     [array1 sortUsingSelector:@selector(compare:)];//這個方法會修改array1     NSLog(@"%@",array1);     /*結果:      (          1,          2,          3      )      */      }   int main(int argc, const char * argv[]) {          test1();          test2();          return 0; } 可變數組中的元素後面必須加nil以表示數據結束; 往一個可變數組中添加一個對象,此時這個對象的引用計數器會加1,當這個對象從可變數組中移除其引用計數器減1。同時當整個數組銷毀之後會依次調用每個對象的releaes方法。 在不可變數組中無論對數組怎麼排序,原來的數組順序都不會改變,但是在可變數組中如果使用sortUsingSelector:排序原來的數組順序就發生了變化。     字典 字典在我們日常開發中也是比較常用的,通過下面的代碼我們看一下在ObjC中的字典的常用操作:初始化、遍歷、排序   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>     void test1(){     NSDictionary *dic1=[NSDictionary dictionaryWithObject:@"1" forKey:@"a"];     NSLog(@"%@",dic1);     /*結果:      {         a = 1;      }      */          //常用的方式     NSDictionary *dic2=[NSDictionary dictionaryWithObjectsAndKeys:                         @"1",@"a",                         @"2",@"b",                         @"3",@"c",                         nil];     NSLog(@"%@",dic2);     /*結果:      {          a = 1;          b = 2;          c = 3;      }      */               NSDictionary *dic3=[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1",@"2", nil] forKeys:[NSArray arrayWithObjects:@"a",@"b", nil]];     NSLog(@"%@",dic3);     /*結果:      {          a = 1;          b = 2;      }      */               //更簡單的方式     NSDictionary *dic4=@{@"1":@"a",@"2":@"b",@"3":@"c"};     NSLog(@"%@",dic4);     /*結果:      {          1 = a;          2 = b;          3 = c;      }      */ } void test2(){     NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys:                         @"1",@"a",                         @"2",@"b",                         @"3",@"c",                         @"2",@"d",                         nil];     NSLog(@"%zi",[dic1 count]); //結果:4     NSLog(@"%@",[dic1 valueForKey:@"b"]);//根據鍵取得值,結果:2     NSLog(@"%@",dic1[@"b"]);//還可以這樣讀取,結果:2     NSLog(@"%@,%@",[dic1 allKeys],[dic1 allValues]);     /*結果:      (          d,          b,          c,          a      ),(          2,          2,          3,          1      )        */          NSLog(@"%@",[dic1 objectsForKeys:[NSArray arrayWithObjects:@"a",@"e" , nil]notFoundMarker:@"not fount"]);//後面一個參數notFoundMarker是如果找不到對應的key用什麼值代替     /*結果:      (          1,          "not fount"      )      */ } void test3(){     NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys:                         @"1",@"a",                         @"2",@"b",                         @"3",@"c",                         @"2",@"d",                         nil];     //遍歷1     for (id key in dic1) {//注意對於字典for遍歷循環的是key         NSLog(@"%@=%@",key,[dic1 objectForKey:key]);     }     /*結果:      d=2      b=2      c=3      a=1      */          //遍歷2     NSEnumerator *enumerator=[dic1 keyEnumerator];//還有值的迭代器[dic1 objectEnumerator]     id key=nil;     while (key=[enumerator nextObject]) {         NSLog(@"%@=%@",key,[dic1 objectForKey:key]);              }     /*結果:      d=2      b=2      c=3      a=1      */          //遍歷3     [dic1 enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {         NSLog(@"%@=%@",key,obj);     }];     /*結果:      d=2      b=2      c=3      a=1      */ }   void test4(){     NSMutableDictionary *dic=[NSMutableDictionary dictionaryWithObjectsAndKeys:@"1",@"a",                               @"2",@"b",                               @"3",@"c",                               @"2",@"d",                             nil];     [dic removeObjectForKey:@"b"];     NSLog(@"%@",dic);     /*結果:      {          a = 1;          c = 3;          d = 2;      }      */          [dic addEntriesFromDictionary:@{@"e":@"7",@"f":@"6"}];     NSLog(@"%@",dic);     /*結果:      {          a = 1;          c = 3;          d = 2;          e = 7;          f = 6;      }      */          [dic setValue:@"5" forKey:@"a"];     NSLog(@"%@",dic);     /*結果:      {          a = 5;          c = 3;          d = 2;          e = 7;          f = 6;      }      */                //注意,一個字典的key或value添加到字典中時計數器+1;字典釋放時調用key或value的release一次,計數器-1 }     int main(int argc, const char * argv[]) {     test1();     test2();     test3();     test4();     return 0; } 注意:同數組一樣,不管是可變字典還是不可變字典初始化元素後面必須加上nil以表示結束。   裝箱和拆箱 其實從上面的例子中我們也可以看到,數組和字典中只能存儲對象類型,其他基本類型和結構體是沒有辦法放到數組和字典中的,當然你也是無法給它們發送消息的(也就是說有些NSObject的方法是無法調用的),這個時候通常會用到裝箱(boxing)和拆箱(unboxing)。其實各種高級語言基本上都有裝箱和拆箱的過程,例如C#中我們將基本數據類型轉化為Object就是一個裝箱的過程,將這個Object對象轉換為基本數據類型的過程就是拆箱,而且在C#中裝箱的過程可以自動完成,基本數據類型可以直接賦值給Object對象。但是在ObjC中裝箱的過程必須手動實現,ObjC不支持自動裝箱。   在ObjC中我們一般將基本數據類型裝箱成NSNumber類型(當然它也是NSObject的子類,但是NSNumber不能對結構體裝箱),調用其對應的方法進行轉換:   +(NSNumber *)numberWithChar:(char)value;   +(NSNumber *)numberWithInt:(int)value;   +(NSNumber *)numberWithFloat:(float)value;   +(NSNumber *)numberWithDouble:(double)value;   +(NSNumber *)numberWithBool:(BOOL)value;   +(NSNumber *)numberWithInteger:(NSInteger)value;   拆箱的過程就更加簡單了,可以調用如下方法:   -(char)charValue;   -(int)intValue;   -(float)floatValue;   -(double)doubleValue;   -(BOOL)boolValue;   簡單看一個例子   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>     /*可以存放基本類型到數組、字典*/ void test1(){     //包裝類NSNumber,可以包裝基本類型但是無法包裝結構體類型     NSNumber *number1=[NSNumber numberWithChar:'a'];//'a'是一個C語言的char類型我們無法放倒NSArray中,但是我們可以通過NSNumber包裝     NSArray *array1=[NSArray arrayWithObject:number1];     NSLog(@"%@",array1);     /*結果:      (         97      )      */          NSNumber *number2= [array1 lastObject];     NSLog(@"%@",number2);//返回的不是基本類型,結果:97               char char1=[number2 charValue];//number轉化為char     NSLog(@"%c",char1); //結果:a }   int main(int argc, const char * argv[]) {     test1();     return  0; } 上面我們看到了基本數據類型的裝箱和拆箱過程,那麼結構體呢?這個時候我們需要引入另外一個類型NSValue,其實上面的NSNumber就是NSValue的子類,它包裝了一些基本數據類型的常用裝箱、拆箱方法,當要對結構體進行裝箱、拆箱操作我們需要使用NSValue,NSValue可以對任何數據類型進行裝箱、拆箱操作。   事實上對於常用的結構體Foundation已經為我們提供好了具體的裝箱方法:   +(NSValue *)valueWithPoint:(NSPoint)point;   +(NSValue *)valueWithSize:(NSSize)size;   +(NSValue *)valueWithRect:(NSRect)rect;   對應的拆箱方法:   -(NSPoint)pointValue;   -(NSSize)sizeValue;   -(NSRect)rectValue;   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>   //NSNumber是NSValue的子類,而NSValue可以包裝任何類型,包括結構體 void test1(){     CGPoint point1=CGPointMake(10, 20);     NSValue *value1=[NSValue valueWithPoint:point1];//對於系統自帶類型一般都有直接的方法進行包裝     NSArray *array1=[NSArray arrayWithObject:value1];//放倒數組中     NSLog(@"%@",array1);     /*結果:      (         "NSPoint: {10, 20}"      )      */          NSValue *value2=[array1 lastObject];     CGPoint point2=[value2 pointValue];//同樣對於系統自帶的結構體有對應的取值方法(例如本例pointValue)     NSLog(@"x=%f,y=%f",point2.x,point2.y);//結果:x=10.000000,y=20.000000 }     int main(int argc, const char * argv[]) {     test1();     return  0; }     那麼如果是我們自定義的結構體類型呢,這個時候我們需要使用NSValue如下方法進行裝箱:   +(NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;   調用下面的方法進行拆箱:   -(void)getValue:(void *)value;   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>   typedef struct {     int year;     int month;     int day; } Date;     //NSNumber是NSValue的子類,而NSValue可以包裝任何類型,包括結構體 void test1(){     //如果我們自己定義的結構體包裝     Date date={2014,2,28};     char *type=@encode(Date);     NSValue *value3=[NSValue value:&date withObjCType:type];//第一參數傳遞結構體地址,第二個參數傳遞類型字符串     NSArray *array2=[NSArray arrayWithObject:value3];     NSLog(@"%@",array2);     /*結果:      (         "<de070000 02000000 1c000000>"      )      */          Date date2;     [value3 getValue:&date2];//取出對應的結構體,注意沒有返回值     //[value3 objCType]//取出包裝內容的類型     NSLog(@"%i,%i,%i",date2.year,date2.month,date2.day); //結果:2014,2,28      }     int main(int argc, const char * argv[]) {     test1();     return  0; } 擴展1-NSNull   通過前面的介紹大家都知道無論在數組還是在字典中都必須以nil結尾,否則數組或字典無法判斷是否這個數組或字典已經結束(與C語言中的字符串比較類似,C語言中定義字符串後面必須加一個”\0”)。但是我們有時候確實想在數據或字典中存儲nil值而不是作為結束標記怎麼辦呢?這個時候需要使用NSNull,這個類是一個單例,只有一個null方法。簡單看一下:   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>       int main(int argc, const char * argv[]) {          NSNull *nl=[NSNull null];//注意這是一個對象,是一個單例,只有一個方法null創建一個對象     NSNull *nl2=[NSNull null];     NSLog(@"%i",nl==nl2);//由於是單例所以地址相等,結果:1          NSArray *array1=[NSArray arrayWithObjects:@"abc",nl,@123, nil];     NSLog(@"%@",array1);     /*結果:      (          abc,          "<null>",          123      )      */       return  0; }     擴展2-@符號   我們知道在ObjC中很多關鍵字前都必須加上@符號,例如@protocol、@property等,當然ObjC中的字符串必須使用@符號,還有就是%@可以表示輸出一個對象。其實@符號在新版的ObjC中還有一個作用:裝箱。   相信聰明的童鞋在前面的例子中已經看到了,這裡簡單的介紹一下(在下面的演示中你也將看到很多ObjC新特性)。   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>   typedef enum {     spring,     summer,     autumn,     winter } Season;   int main(int argc, const char * argv[]) {     /*裝箱*/     NSNumber *number1=@100;     NSArray *array1=[NSArray arrayWithObjects:number1,@"abc",@16,@'A',@16.7,@YES, nil];     NSLog(@"%@",array1);     /*結果:      (          100,          abc,          16,          65,          "16.7"          1      )      */     NSNumber *number2=@(1+2*3);     NSLog(@"%@",number2); //結果:7     NSNumber *number3=@(autumn);     NSLog(@"%@",number3); //結果:2            NSArray *array2=@[@"abc",@16,@'A',@16.7,@YES];//使用這種方式最後不用添加nil值了     NSLog(@"%@",array2[2]); //結果:65     NSMutableArray *array3=[NSMutableArray arrayWithArray:array2];     array3[0]=@"def";     NSLog(@"%@",array3[0]); //結果:def          NSDictionary *dic1=@{@"a":@123,@"b":@'c',@"c":@YES};     NSLog(@"%@",dic1);     /*結果:      {          a = 123;          b = 99;          c = 1;      }      */     NSMutableDictionary *dic2=[NSMutableDictionary dictionaryWithDictionary:dic1];     dic2[@"a"]=@456;     NSLog(@"%@",dic2[@"a"]);//結果:456       return 0; } 反射 由於ObjC動態性,在ObjC中實現反射可以說是相當簡單,下面代碼中演示了常用的反射操作,具體作用也都在代碼中進行了注釋說明:   Account.h   // //  Account.h //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h>   @interface Account : NSObject   @property (nonatomic,assign) double balance;   @end Account.m   // //  Account.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import "Account.h"   @implementation Account   @end Person.h   // //  Person.h //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h> @class Account;   @interface Person : NSObject   @property (nonatomic,copy) NSString *name; @property (nonatomic,retain) Account *account;   -(Person *)initWithName:(NSString *)name;   +(Person *)personWithName:(NSString *)name;   -(void)showMessage:(NSString *)infomation;   //自己實現對象比較方法 -(NSComparisonResult)comparePerson:(Person *)person; @end Person.m   // //  Person.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import "Person.h"   @implementation Person   -(Person *)initWithName:(NSString *)name{     if(self=[super init]){         self.name=name;     }     return self; }   +(Person *)personWithName:(NSString *)name{     Person *person=[[Person alloc]initWithName:name];     return person; }   -(void)showMessage:(NSString *)infomation{     NSLog(@"My name is %@,the infomation is \"%@\".",_name,infomation); }   //自己實現對象比較方法 -(NSComparisonResult)comparePerson:(Person *)person{     return [_name compare:person.name]; }   -(NSString *)description{     return [NSString stringWithFormat:@"name=%@",_name]; }   @end main.m   // //  main.m //  FoundationFramework // //  Created by Kenshin Cui on 14-2-16. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. //   #import <Foundation/Foundation.h> #import "Person.h"     int main(int argc, const char * argv[]) {     /*常用方法*/     Person *person1=[Person personWithName:@"Kenshin"];     NSLog(@"%i",[person1 isKindOfClass:[NSObject class]]); //判斷一個對象是否為某種類型(如果是父類也返回YES),結果:1     NSLog(@"%i",[person1 isMemberOfClass:[NSObject class]]); //判斷一個對象是否是某個類的實例化對象,結果:0     NSLog(@"%i",[person1 isMemberOfClass:[Person class]]); //結果:1     NSLog(@"%i",[person1 conformsToProtocol:@protocol(NSCopying)]);//是否實現了某個協議,結果:0     NSLog(@"%i",[person1 respondsToSelector:@selector(showMessage:)]);//是否存在某個方法,結果:1          [person1 showMessage:@"Hello,world!"];//直接調用一個方法     [person1 performSelector:@selector(showMessage:) withObject:@"Hello,world!"];     //動態調用一個方法,注意如果有參數那麼參數類型只能為ObjC對象,並且最多只能有兩個參數            /*反射*/     //動態生成一個類     NSString *className=@"Person";     Class myClass=NSClassFromString(className);//根據類名生成類     Person *person2=[[myClass alloc]init]; //實例化     person2.name=@"Kaoru";     NSLog(@"%@",person2);//結果:name=Kaoru       //類轉化為字符串     NSLog(@"%@,%@",NSStringFromClass(myClass),NSStringFromClass([Person class])); //結果:Person,Person       //調用方法     NSString *methodName=@"showMessage:";     SEL mySelector=NSSelectorFromString(methodName);     Person *person3=[[myClass alloc]init];     person3.name=@"Rosa";     [person3 performSelector:mySelector withObject:@"Hello,world!"]; //結果:My name is Rosa,the infomation is "Hello,world!".       //方法轉化為字符串     NSLog(@"%@",NSStringFromSelector(mySelector)); //結果:showMessage:          return 0; }
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved