.net 碼農(nóng)轉(zhuǎn)戰(zhàn) iOS - 初探
好久沒(méi)寫(xiě)博客了,之前還打算把畢業(yè)設(shè)計(jì)中涉及到的兩個(gè)算法拿出來(lái)說(shuō)說(shuō)(臉型分析 + 聲音分析),博文都寫(xiě)了一半了,后來(lái)實(shí)在太忙了,那篇隨筆也就沉在草稿列表中沒(méi)動(dòng)過(guò)。 我原先是專(zhuān)職 .net 開(kāi)發(fā)的,在公司負(fù)責(zé)的項(xiàng)目是內(nèi)部自用的銷(xiāo)售管理系統(tǒng),由于不需要出去"拋頭露臉",所以公司干脆什么也沒(méi)配置(指產(chǎn)品、設(shè)計(jì)、前端等等,開(kāi)發(fā)設(shè)備還是有的),于是所有工作全包了。原本對(duì)自身的計(jì)劃是,后續(xù)會(huì)慢慢轉(zhuǎn)產(chǎn)品方面的。 后來(lái),也算是一個(gè)契機(jī),公司所有移動(dòng)端的人基本走光了(iOS 全走了,Android 的好像只剩 2 個(gè)!!公司內(nèi)部的事,這里就不多說(shuō)了),于是上頭經(jīng)理就打算讓我們轉(zhuǎn)到移動(dòng)端開(kāi)發(fā)。.net 和 java 一直都是"死對(duì)頭"(自己的理解,求別噴),所以我不會(huì)選 Android,WP 市場(chǎng)還不夠,轉(zhuǎn)過(guò)去對(duì)自己競(jìng)爭(zhēng)力的提升不大,于是乎選擇了 iOS 開(kāi)發(fā),于是乎便有了這篇《.net 碼農(nóng)轉(zhuǎn)戰(zhàn) iOS - 初探》。。。 大學(xué)時(shí)期有一點(diǎn) C 的基礎(chǔ),但是對(duì) OC 完全不知,這次屬于從 0 開(kāi)始(不選擇 swift 開(kāi)始,其實(shí)是怕它還不夠成熟。語(yǔ)言這東西,其實(shí)說(shuō)到底是相通的,理解了基礎(chǔ)的東西,還怕以后學(xué)不會(huì)其他的么!)。 我是屬于自學(xué)的,看視頻、查資料一步步慢慢走。 學(xué)習(xí)真的需要?jiǎng)邮智面I盤(pán),單單只是看一下是記不住理解不了的,至少我還沒(méi)到那個(gè)看看就會(huì)的地步。。。 · 我從 xcode5 開(kāi)始,這時(shí)候已經(jīng)少了很多內(nèi)存管理的代碼了(基本不用寫(xiě) release 了),但是不需要你寫(xiě),并不代表不需要你了解。所以內(nèi)存管理需要詳看。 · 命名空間,OC 里是沒(méi)有這個(gè)概念的。區(qū)分兩個(gè)不同的類(lèi),僅僅是依靠類(lèi)名。所以一般都會(huì)在真正類(lèi)名前,加一個(gè)前綴用來(lái)區(qū)分,例如 NSString(NS 開(kāi)頭的代表為 MAC OS X 的核心,即 NeXTSTEP 的縮寫(xiě))、CGPoint。。。許多程序員都會(huì)使用自己名字的縮寫(xiě)做類(lèi)的前綴。 · OC 大量使用指針,而且需顯性表示(NSString *str; str 是一個(gè)指針變量,前面需加一個(gè) "*" 顯性體現(xiàn),表示它是一個(gè)指向 "字符串" 的變量)。.net 中也有這個(gè)概念,只是不需要顯性表明("*"),參考 .net 中,類(lèi)、string 的聲明。 · @"",OC 中字符串的寫(xiě)法,前面必須加一個(gè) "@" 表示是 NSString 類(lèi)型; · NSLog() 方法,即 .net 中 Console.WriteLine 方法,支持字符串的 Format,例如 NSLog(@"%@, %i, %f", @"1", 1, 1.0);(@"%@" 功能很強(qiáng)大,類(lèi)似于 .net 中 ToString() 方法)。 · 類(lèi)的聲明,創(chuàng)建一個(gè)普通的類(lèi),包含一個(gè) .h 文件和一個(gè) .m 文件(例如 SLTest.h & SLTest.m),是成對(duì)出現(xiàn)的,.h 文件為頭文件,一般用來(lái)做類(lèi)的聲明,類(lèi)似 .net 里的抽象類(lèi);.m 文件為實(shí)現(xiàn)文件,用來(lái)實(shí)現(xiàn)對(duì)應(yīng)的"抽象類(lèi)"。/**SLTest.h**///使用import引入頭文件//Foundation為基礎(chǔ)框架//import表示該頭文件只被包含一次,無(wú)論該命令在整個(gè)程序中出現(xiàn)多少次#import<Foundation/Foundation.h>//用interface標(biāo)明是類(lèi)的聲明//該類(lèi)繼承自NSObject,類(lèi)似.net里的基類(lèi)object@interfaceSLTest:NSObject{//聲明成員變量}//聲明公有方法@end/**SLTest.m**///使用import引入頭文件#import"SLTest.h"//implementation標(biāo)明是類(lèi)的實(shí)現(xiàn)@implementationSLTest//定義、實(shí)現(xiàn)私有方法//實(shí)現(xiàn)公有方法@end
· OC 中聲明類(lèi)使用 interface 關(guān)鍵字,實(shí)現(xiàn)類(lèi)使用 implementation 關(guān)鍵字。其實(shí) OC 中還有一個(gè)關(guān)鍵字 "class",它并非 "聲明類(lèi)" 的意思,而是 "包含類(lèi)" 的意思。功能與 import 相似,但使用 import,編譯時(shí)會(huì)將 import 的文件整個(gè)包含進(jìn)來(lái),而使用 class,編譯時(shí)只是告訴它已經(jīng)有這個(gè)類(lèi),而不會(huì)整個(gè)包含進(jìn)來(lái),比 import 更輕量級(jí)。多用在只需要知道類(lèi)名,而不需要使用類(lèi)中方法的地方(例如變量聲明等)。使用方法:@class SLTest;。最大好處,例如有兩個(gè)類(lèi):A、B,A 中有一個(gè)變量 B b;,B 中有一個(gè)變量 A a;,如果使用 import,那么編譯時(shí)就是"我中有你你中有我",互相包含,最后造成包含的死循環(huán)。 · OC 中方法的調(diào)用是使用 "[]",例如 [aaa AAA],在 .net 中即表現(xiàn)為 aaa.AAA(); 。有參數(shù)的方法調(diào)用例如 [aaa BBB:1 CCC:2],在 .net 中表現(xiàn)為 aaa.BBB:CCC:(1, 2); 。注意,OC 中 ":" 也是方法名,有多少個(gè) ":" 表示有多少個(gè)參數(shù),而參數(shù)的傳入是嵌套在方法名中的(怎么定義怎么用,例如剛才有參數(shù)的方法,定義為 -(void)BBB:(NSInteger)i CCC:(NSInteger)j;),這點(diǎn)和 .net 有很大的不同。 · 實(shí)例化一個(gè)對(duì)象,由于要考慮到內(nèi)存管理問(wèn)題,OC 中基本都是用 alloc + initXXX 方法(也有個(gè)別使用其他工廠模式方法,在此不包括),alloc 表示分配內(nèi)存,initXXX 表示初始化。基本使用方法:[[NSString alloc] initWithFormat:@"this is a string."]。這里的意思是實(shí)例化一個(gè) NSString 對(duì)象,指向 "this is a string." 的內(nèi)存塊(initWithFormat:() 是 NSString 自有方法,其他類(lèi)型也有類(lèi)似的 initXXX() 的方法,也有的只有 init() 方法)。當(dāng)然 OC 也有 new() 方法,但是不建議使用。還是 .net 的 new() 好用!!OC 中沒(méi)有重載,只能用方法名來(lái)區(qū)分。例如 NSString 中的 initWithFormat() 方法和 initWithCoder()。還是 .net 的 new() 好用!!· get/set 方法,.net 中我們是使用 { get; set; } 讓編譯器自動(dòng)為我們添加,OC 也有類(lèi)似的:// 使用 property 關(guān)鍵字聲明// 括號(hào)內(nèi)指定該屬性的形式:// nonatomic 表示線程不安全的,在單線程不考慮線程安全的情況,使用 nonatomic 就可以了,對(duì)應(yīng)的 atomic// 一般基礎(chǔ)類(lèi)型用 assign,NSString 用 copy,其他用 strong(retain),當(dāng)然,凡事也有例外,具體自行谷哥吧// 此外還有 readonly、getter 等等,自行谷哥吧@property (nonatomic, assign) BOOL balabalabala;
只需要這句話,編譯器會(huì)自動(dòng)生成私有的成員變量和對(duì)應(yīng)的 get/set 方法,當(dāng)然也可以自己重寫(xiě) get/set 方法,在 .m 文件中實(shí)現(xiàn)即可。 · 方法前面,"-" 表示是實(shí)例方法,即由實(shí)例調(diào)用;"+" 表示是類(lèi)方法,即 .net 中類(lèi)的靜態(tài)方法。 · OC 中的 id 類(lèi)型,弱類(lèi)型,類(lèi)似 js 里的 var,硬要跟 .net 掛鉤的話,很像 dynamic,但貌似又跟 dynamic 有所不同,請(qǐng)?jiān)徫阴磕_的表達(dá)能力。。。 · self 關(guān)鍵字,即 .net 中的 this 關(guān)鍵字;super 關(guān)鍵字,即 .net 中的 base 關(guān)鍵字。 · block,也就是 .net 中的匿名函數(shù),定義順序是:返回類(lèi)型、"^"關(guān)鍵字、方法名(若聲明位置是方法參數(shù),可省略)、參數(shù)列表,例如:// 返回類(lèi)型為空// 方法名為 TEST1// 參數(shù)列表為空void (^TEST1)(void) = ^ {NSLog(@"TEST1");};TEST1();// 返回類(lèi)型為 NSString *// 方法名為 TEST2// 需傳入一個(gè) NSInteger 類(lèi)型的參數(shù)NSString *(^TEST2)(NSInteger) = ^(NSInteger i) {NSLog(@"TEST2 parameter: %i", i);return @"test2";};NSString *result = TEST2(10);NSLog(@"%@", result);// TEST3 方法定義了一個(gè) block 參數(shù),該 block 無(wú)返回值,需傳入一個(gè) NSString 類(lèi)型的參數(shù)- (void)TEST3:(void (^)(NSString * parameter))block{NSLog(@"TEST3");// 調(diào)用 block,并傳入?yún)?shù)block(@"TEST3 parameter");}// 調(diào)用 TEST3,傳入 block[self TEST3:^(NSString *parameter){NSLog(@"parameter: %@", parameter);}];
用法同 .net 的無(wú)異,只是語(yǔ)法不同。 · category,擴(kuò)展,即 .net 中的類(lèi)擴(kuò)展,例如 public static bool IsValidEmailAddress(this string str);。OC 中,只允許擴(kuò)展方法,寫(xiě)法:/**NSString+Category.h文件命名方法,OC 建議是原類(lèi)名+擴(kuò)展名**/// 聲明時(shí),原類(lèi)名后加一個(gè)括號(hào),括號(hào)里為擴(kuò)展名,表示這是一個(gè)擴(kuò)展@interface NSString (Category)// 擴(kuò)展一個(gè)方法,判斷該字符串是否為 Email 地址- (BOOL)isValidEmailAddress;@end/**NSString+Category.m**/@implementation NSString (Category)// 實(shí)現(xiàn)方法// 請(qǐng)忽略具體方法,這里只做演示- (BOOL)isValidEmailAddress{return [self length] % 2 == 0;}@end// 使用時(shí),引入 .h 文件,即可像普通類(lèi)方法一樣使用NSString *str1 = @"1";NSString *str2 = @"11";NSLog(@"%i", [str1 isValidEmailAddress]);NSLog(@"%i", [str2 isValidEmailAddress]);
· delegate,協(xié)議,注意,這里并不同 .net 中的 delegate,.net 中的 delegate 應(yīng)該更類(lèi)似 OC 中的 block。這里的 delegate 更像是 .net 中的接口。用我自己的理解來(lái)說(shuō),就是我有時(shí)候會(huì)觸發(fā)某個(gè)事件,而你如果需要知道我何時(shí)觸發(fā)了事件,那么我們之間就必須有一種 "約定協(xié)議",即當(dāng)我觸發(fā)事件時(shí),通知你。而你收到我的通知后,要干嘛,那是你的自由了。 這里所說(shuō)的 "約定協(xié)議",即 OC 中的 delegate。我要通知你,即使用 delegate 中的方法。你只需要實(shí)現(xiàn)這個(gè)方法,我就可以通知到你。這個(gè)在下一篇再進(jìn)行詳細(xì)說(shuō)明。 OC 的一些基礎(chǔ)的東西就差不多了,接下來(lái)就是結(jié)合到界面的開(kāi)發(fā),形式很像 .net 的 winform 開(kāi)發(fā),iOS 中使用 MVC 框架,所以如果你 .net 會(huì)這兩樣的話,還是比較容易看得懂的。 做一款像樣的 App,需要各種崗位的同事幫忙,從需求,到設(shè)計(jì)、編碼、測(cè)試、上線,確實(shí)考驗(yàn)一個(gè)團(tuán)隊(duì)的合作能力。
/** SLTest.h **/ //使用import引入頭文件 //Foundation為基礎(chǔ)框架 //import表示該頭文件只被包含一次,無(wú)論該命令在整個(gè)程序中出現(xiàn)多少次 #import<Foundation/Foundation.h> //用interface標(biāo)明是類(lèi)的聲明 //該類(lèi)繼承自NSObject,類(lèi)似.net里的基類(lèi)object @interfaceSLTest:NSObject { //聲明成員變量 } //聲明公有方法 @end /** SLTest.m **/ //使用import引入頭文件 #import"SLTest.h" //implementation標(biāo)明是類(lèi)的實(shí)現(xiàn) @implementationSLTest //定義、實(shí)現(xiàn)私有方法 //實(shí)現(xiàn)公有方法 @end |
· OC 中聲明類(lèi)使用 interface 關(guān)鍵字,實(shí)現(xiàn)類(lèi)使用 implementation 關(guān)鍵字。其實(shí) OC 中還有一個(gè)關(guān)鍵字 "class",它并非 "聲明類(lèi)" 的意思,而是 "包含類(lèi)" 的意思。功能與 import 相似,但使用 import,編譯時(shí)會(huì)將 import 的文件整個(gè)包含進(jìn)來(lái),而使用 class,編譯時(shí)只是告訴它已經(jīng)有這個(gè)類(lèi),而不會(huì)整個(gè)包含進(jìn)來(lái),比 import 更輕量級(jí)。多用在只需要知道類(lèi)名,而不需要使用類(lèi)中方法的地方(例如變量聲明等)。使用方法:@class SLTest;。最大好處,例如有兩個(gè)類(lèi):A、B,A 中有一個(gè)變量 B b;,B 中有一個(gè)變量 A a;,如果使用 import,那么編譯時(shí)就是"我中有你你中有我",互相包含,最后造成包含的死循環(huán)。
· OC 中方法的調(diào)用是使用 "[]",例如 [aaa AAA],在 .net 中即表現(xiàn)為 aaa.AAA(); 。有參數(shù)的方法調(diào)用例如 [aaa BBB:1 CCC:2],在 .net 中表現(xiàn)為 aaa.BBB:CCC:(1, 2); 。注意,OC 中 ":" 也是方法名,有多少個(gè) ":" 表示有多少個(gè)參數(shù),而參數(shù)的傳入是嵌套在方法名中的(怎么定義怎么用,例如剛才有參數(shù)的方法,定義為 -(void)BBB:(NSInteger)i CCC:(NSInteger)j;),這點(diǎn)和 .net 有很大的不同。
· 實(shí)例化一個(gè)對(duì)象,由于要考慮到內(nèi)存管理問(wèn)題,OC 中基本都是用 alloc + initXXX 方法(也有個(gè)別使用其他工廠模式方法,在此不包括),alloc 表示分配內(nèi)存,initXXX 表示初始化。基本使用方法:[[NSString alloc] initWithFormat:@"this is a string."]。這里的意思是實(shí)例化一個(gè) NSString 對(duì)象,指向 "this is a string." 的內(nèi)存塊(initWithFormat:() 是 NSString 自有方法,其他類(lèi)型也有類(lèi)似的 initXXX() 的方法,也有的只有 init() 方法)。當(dāng)然 OC 也有 new() 方法,但是不建議使用。還是 .net 的 new() 好用!!OC 中沒(méi)有重載,只能用方法名來(lái)區(qū)分。例如 NSString 中的 initWithFormat() 方法和 initWithCoder()。還是 .net 的 new() 好用!!
· get/set 方法,.net 中我們是使用 { get; set; } 讓編譯器自動(dòng)為我們添加,OC 也有類(lèi)似的:
// 使用 property 關(guān)鍵字聲明 // 括號(hào)內(nèi)指定該屬性的形式: // nonatomic 表示線程不安全的,在單線程不考慮線程安全的情況,使用 nonatomic 就可以了,對(duì)應(yīng)的 atomic // 一般基礎(chǔ)類(lèi)型用 assign,NSString 用 copy,其他用 strong(retain),當(dāng)然,凡事也有例外,具體自行谷哥吧 // 此外還有 readonly、getter 等等,自行谷哥吧 @property (nonatomic, assign) BOOL balabalabala; |
只需要這句話,編譯器會(huì)自動(dòng)生成私有的成員變量和對(duì)應(yīng)的 get/set 方法,當(dāng)然也可以自己重寫(xiě) get/set 方法,在 .m 文件中實(shí)現(xiàn)即可。
· 方法前面,"-" 表示是實(shí)例方法,即由實(shí)例調(diào)用;"+" 表示是類(lèi)方法,即 .net 中類(lèi)的靜態(tài)方法。
· OC 中的 id 類(lèi)型,弱類(lèi)型,類(lèi)似 js 里的 var,硬要跟 .net 掛鉤的話,很像 dynamic,但貌似又跟 dynamic 有所不同,請(qǐng)?jiān)徫阴磕_的表達(dá)能力。。。
· self 關(guān)鍵字,即 .net 中的 this 關(guān)鍵字;super 關(guān)鍵字,即 .net 中的 base 關(guān)鍵字。
· block,也就是 .net 中的匿名函數(shù),定義順序是:返回類(lèi)型、"^"關(guān)鍵字、方法名(若聲明位置是方法參數(shù),可省略)、參數(shù)列表,例如:
// 返回類(lèi)型為空 // 方法名為 TEST1 // 參數(shù)列表為空 void (^TEST1)(void) = ^ { NSLog(@"TEST1"); }; TEST1(); // 返回類(lèi)型為 NSString * // 方法名為 TEST2 // 需傳入一個(gè) NSInteger 類(lèi)型的參數(shù) NSString *(^TEST2)(NSInteger) = ^(NSInteger i) { NSLog(@"TEST2 parameter: %i", i); return @"test2"; }; NSString *result = TEST2(10); NSLog(@"%@", result); // TEST3 方法定義了一個(gè) block 參數(shù),該 block 無(wú)返回值,需傳入一個(gè) NSString 類(lèi)型的參數(shù) - (void)TEST3:(void (^)(NSString * parameter))block { NSLog(@"TEST3"); // 調(diào)用 block,并傳入?yún)?shù) block(@"TEST3 parameter"); } // 調(diào)用 TEST3,傳入 block [self TEST3:^(NSString *parameter) { NSLog(@"parameter: %@", parameter); }]; |
用法同 .net 的無(wú)異,只是語(yǔ)法不同。
· category,擴(kuò)展,即 .net 中的類(lèi)擴(kuò)展,例如 public static bool IsValidEmailAddress(this string str);。OC 中,只允許擴(kuò)展方法,寫(xiě)法:
/** NSString+Category.h 文件命名方法,OC 建議是原類(lèi)名+擴(kuò)展名 **/ // 聲明時(shí),原類(lèi)名后加一個(gè)括號(hào),括號(hào)里為擴(kuò)展名,表示這是一個(gè)擴(kuò)展 @interface NSString (Category) // 擴(kuò)展一個(gè)方法,判斷該字符串是否為 Email 地址 - (BOOL)isValidEmailAddress; @end /** NSString+Category.m **/ @implementation NSString (Category) // 實(shí)現(xiàn)方法 // 請(qǐng)忽略具體方法,這里只做演示 - (BOOL)isValidEmailAddress { return [self length] % 2 == 0; } @end // 使用時(shí),引入 .h 文件,即可像普通類(lèi)方法一樣使用 NSString *str1 = @"1"; NSString *str2 = @"11"; NSLog(@"%i", [str1 isValidEmailAddress]); NSLog(@"%i", [str2 isValidEmailAddress]); |
· delegate,協(xié)議,注意,這里并不同 .net 中的 delegate,.net 中的 delegate 應(yīng)該更類(lèi)似 OC 中的 block。這里的 delegate 更像是 .net 中的接口。用我自己的理解來(lái)說(shuō),就是我有時(shí)候會(huì)觸發(fā)某個(gè)事件,而你如果需要知道我何時(shí)觸發(fā)了事件,那么我們之間就必須有一種 "約定協(xié)議",即當(dāng)我觸發(fā)事件時(shí),通知你。而你收到我的通知后,要干嘛,那是你的自由了。
這里所說(shuō)的 "約定協(xié)議",即 OC 中的 delegate。我要通知你,即使用 delegate 中的方法。你只需要實(shí)現(xiàn)這個(gè)方法,我就可以通知到你。這個(gè)在下一篇再進(jìn)行詳細(xì)說(shuō)明。
OC 的一些基礎(chǔ)的東西就差不多了,接下來(lái)就是結(jié)合到界面的開(kāi)發(fā),形式很像 .net 的 winform 開(kāi)發(fā),iOS 中使用 MVC 框架,所以如果你 .net 會(huì)這兩樣的話,還是比較容易看得懂的。
做一款像樣的 App,需要各種崗位的同事幫忙,從需求,到設(shè)計(jì)、編碼、測(cè)試、上線,確實(shí)考驗(yàn)一個(gè)團(tuán)隊(duì)的合作能力。
posted on 2014-08-06 10:33 順其自然EVO 閱讀(555) 評(píng)論(0) 編輯 收藏