簡介當我開始爲iOS寫代碼的時候,我意識到,做爲一個C++開發者,我必須花費更多的時間來弄清楚Objective-C中怪異的東西。這就是一個幫助C++專家的快速指南,可以使他們快速的掌握Apple的iOS語言。html 請注意這毫不是一個完整的指南,可是它讓你避免了閱讀100頁的手冊。除此以外,我知道你喜歡個人寫做風格。java 背景須要C++的技能,我會比較C++和Objective-C的東西。此外,COM編程也是有用的,由於Objective-C有相似於IUnkown的東西,所以基礎的COM編程是有幫助的(但不是必須的)程序員 Objective C++是C++和Objective C的組合。你也能使用任何C++的東西混合到Objective C中,可是記住從新命名你的文件從.m到.mmobjective-c |
![]() 地獄星星
|
其它翻譯版本(2) |
鐺 - 鐺!咱們立刻就開始咱們的教程. 首先我會介紹 Objective-C 的東西,而後是C++中與它對等的東西.數組 成員函數多線程
- 表示的是一個通常的成員函數(經過一個對象實體訪問), 而 + 則表示一個靜態成員函數, 不須要使用實體就能訪問. 固然,像C++, 靜態成員不能訪問實體變量.app 此外,Objective-C函數函數能夠有賦予了名稱的參數,這樣讓什麼參數得到什麼值會更一目瞭然. 理論上,被賦予了名稱的參數容許程序員按任何順序傳入參數,可是Objective-C卻規定要按聲明的順序傳參.編輯器 經過一個指針或者一個靜態成員調用一個成員
Objective-C 使用 [ ] 來調用成員函數並傳入用:分割開的參數, 其對於ObjectiveC中ptr爲nil的狀況很是友好,在這種狀況下「調用」將會被忽略掉(而在C++中,這種狀況會拋出一個指針衝突異常 ). 這使得消除對nil對象的檢查成爲可能. |
![]() leoxu
|
協議VS接口
協議= 抽象類. Objective-C 和 C++ 之間的區別在於,在 Objective-C 中, 函數並非必需要被實現的. 你可讓一個可選的方法被動的被聲明,而這僅僅只是向編譯器發出暗示而已,並非編譯必須的. 檢查一個方法是否被實現了
Objective-C 成員函數就是(Smalltalk中的) "消息" 而在Objective-C中時,咱們則說接收者 (即指針) 會向一個選擇器作出迴應, 這意味着其實現了咱們嘗試去調用的虛函數. 當有一個接口是, C++ 對象必須實現其全部的成員函數. 而在 Objective-C 中這並非必須的,所以咱們能夠向並沒必要需要實現它的某個地方發送一個」消息「 (如此就會引起一個異常).
如今咱們就能夠肯定接收者向選擇器作出迴應, 咱們所以就能夠調用它了. 在 C++ 中不須要這樣的檢查, 由於實現必須經常」向選擇器作出迴應「, 不然源代碼根本就不會被編譯. 請注意咱們必須知道選擇器獲取了多少個參數(所以在該@selector中是2個 ::s |
![]() leoxu
|
向下轉型
如今只有使用NSObject的"isKindOfClass"助手——全部Object-C類的基礎,才能像在C++中那樣向下轉型. 符合協議?
如今咱們要檢查接收器是否 符合一個協議 (或者說,在C++就是實現一個接口), 以便咱們能夠發送這個協議包含的消息. 嘿嘿,它像極了Java的類和接口,而在C++中,徹底被實現的類和一個「接口」之間沒有技術上的差異. void* 、 id 或者 SEL?
id 是通用的用於Objective-C類的相似於 void* 的東西. 你只能使用id而不是 void* 由於id能夠經過ARC(稍後會詳細介紹到它)編程一個可被管理的指針,而所以編譯器須要在元指針類型和Objective-C指針之間作出區分. SEL 是一個用於選擇器(C++函數指針)的通用類型,而你通常能夠經過使用關鍵字@selector帶上函數名字和:::::s的一個數字來建立一個選擇器, 這取決於能夠傳入多少參數. 選擇器實際上就是一個字符串,它會在運行時綁定到一個方法識別器. |
![]() leoxu
|
類定義,方法,數據,繼承
Objective-C中的實現範圍在@implementation/@end 標記 (在 C++ 中咱們能夠將實現放在任何帶有::範圍操做符的地方)之中. 它使用@class關鍵字用於事先聲明. Objective-C 默認帶有 私有(private) 保護, 但僅用於數據成員(方法必須是公共的). Objective-C 使用 self 而不是 this ,而且它還能夠經過super關鍵字調用它的父類.
Objective-C中的內存分配是經過靜態成員方法alloc來實現的,全部 (作爲NSObject後裔)的對象都有這個方法. self 在Objective-C中是能夠被賦值的,而若是構建失敗的話它就會設置成nil(而在C++中則會被拋出一個異常). 內存分配以後實際被構造器調用的是一個公共的成員函數,在Objective-C中默認的是init方法. |
![]() leoxu
|
多線程
Objective-C 有一些針對NSObject的內建功能,能夠在另一個線程中操做一個選擇器 (== 調用一個成員), 在主線程中,等待一次調用等等 . 在NSObject 參見更多信息. 內存和ARC
這裏須要你忘記本身良好的 C++ 習慣. OK Objective-C 使用了一個垃圾收集機制,這種東西咱們C++很討厭,由於它很慢並會讓咱們想到Java. 可是 ARC (自動進行引用計算) 是一種 編譯時間 特性,它會告訴編譯器 "這裏是個人對象:請幫我算算啥時候它們纔要被銷燬吧". 使用ARC你就不須要發送 retain/release 消息給你的對象了; 編譯器會自動幫你代勞的. |
![]() leoxu
|
爲了能幫助編譯器決定保留一個對象多長時間,你還要一個弱引用指向一個變量. 默認的,全部的變量都是強引用(==只要強引用還存在,被引用的對象就會存在下去) . 你也能夠獲取一個弱引用,它會隨着每一個強引用消失而失去它的值. 這在類成員從XCode的Builder Interface(像RC 編輯器)處獲取它們的值時,會頗有用,當類被銷燬時,那些成員也會失去它們的值. Strings
NSString 是一個Objective-C字符串的不可變表示. 你可使用其一個靜態方法,或者是一個帶有@前綴的字符串文原本建立NSString. 你也可使用 %@ 來向printf家族函數來表示一個NSString, |
![]() leoxu
|
數組
NSArray和NSMutableArray是在Objective-C中處理數組的 兩個類(二者的差別是,NSArray元素構造時必須經過構造函數,而NSMutableArray能夠在以後更改)。典型構造函數的生效,你必須經過nil去做爲「結尾元素」。排序/搜索/插入函數對於NSArray和NSMutableArray來講是同樣的,在第一行中的例子它返回一個新的NSArray,而在NSMutableArray的例子裏,它修改的是一個存在的對象。 分類
C++依賴 繼承機制來實現一個已知的類。這是很麻煩的,由於全部用戶的實現類必須使用另外的類型名稱(在例子中,MyString用來代替string)。Object-C經過使用 分類(Categories)容許擴展一個已知的類內 同型(same type)。上面連接中全部源代碼在extension.h文件 (具備表明性的是像NSString+MyString.h這樣的)中能夠查看,上面例子中,咱們當即就有能夠調用新的成員函數,而不須要改變NSString類型爲MyString。 |
![]() 無若
|
塊 和 Lambda
塊 是Objective-C 用來模擬lambda功能的一種方式. 查看Apple的文檔,從AlertView的示例 (使用塊的UIAlertView)能夠得到更多有關塊的技術. C++ 開發者使用 Objective-C 和 ARC 的重要提示
你已經知道給全部的顧客都打兩折對你而言有多痛苦了,由於你bug重重的軟件會在發佈模式下奔潰,而在調試模式下老是妥妥的. 沒有用戶會理解程序員,是否是? 讓咱們來看看這裏發生了什麼. s = 0 這一行將 0 賦值給了一個變量,而所以無論這個變量以前取值是什麼,首先都會被釋放掉,因此編譯器在賦值以前執行了一次 [s release] . 若是 s 以前已是 0 了,假設是在調試構建的話,不會發生任何很差的事情; 若是 s 是一個nil的話,使用[s release] 是再好也不過的. 然而,在發佈模式下, s多是一個野指針,因此它可能在被「初始化」爲0以前包含任何值(這很危險是否是?). |
![]() leoxu
|
在C++中,這並非一個問題,由於它裏面是不存在ARC的. 而在Objective-C中編譯器並無辦法瞭解這是一次"賦值" 仍是一次 "初始化" (若是是後者,它就不會發送發佈消息). 下面是正確的方式:
如今編譯器就不會去嘗試調用一個 [s release] 由於它知道它是這個對象的第一次初始化. 請當心!
從Objective-C 對象到 C++ 類型的轉換
我能夠分析這一切,而個人建議是簡單的. 不要 將ARC類型和非ARC類型混在一塊兒. 若是你必須轉換一些Objective-C對象的話,使用id而不是void*. 不然,你將會遇到嚴重的內存故障. |
![]() leoxu
|
Objective-C 有而 C++ 沒有的
C++ 有而 Objective-C 沒有的
閱讀更多
|