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