有一定 c++或者 java 基礎,過一遍 oc 語法即可,都是相通的,個人認為難點是 oc 的內(nèi)存管理,雖然有了 ARC,但是也需要學習下,因為有舊軟件的維護。
建立在C語言的基礎上,增加了一層小范圍的面向對象的語法(保留了面向對象最精華的部分,oc的內(nèi)容沒有java多,而java的內(nèi)容沒有c++多,c++的內(nèi)容最為繁雜),OC完全兼容C語言,c和oc可以混編。可以在OC代碼中混入C語言代碼(前提是oc源文件擴展名是.m),甚至是C++代碼(不是所有的源文件都能包含c++代碼,只有源文件擴展名是.mm的源文件可以包含c++代碼)。
可以使用OC開發(fā)Mac OS X平臺和iOS平臺的應用程序
關鍵字
基本上所有關鍵字都是以@開頭,一些常見的關鍵字
@interface、@implementation、@end、@public、@PRotected、@private、@selector、@try、@catch、@throw、@finally 、@protocol、@optional、@required、@class、@property、@synthesize、@dynamic、self、super、id、_cmd、__block、__strong、__weak
字符串以@開頭
比如@"Hello"是OC中的字符串,而"Hello"則是C語言中的字符串,其中,@和字符串必須緊挨著。
注釋
注釋的語法和C 一樣。
nil
OC 中的 nil 相當于 c 和 c++的NULL
OC程序的開發(fā)過程
編輯,編譯,鏈接(把所有的相互關聯(lián)的.o文件合并在一起,加上函數(shù)庫),運行。
和c類似,先編寫.m文件(文件名可以是中文),然后編譯器編譯,鏈接,運行。
NSLog與printf的區(qū)別
1、NSLog接收OC字符串作為參數(shù),printf接收C語言字符串作為參數(shù)
2、NSLog輸出后會自動換行,printf輸出后不會自動換行
3、使用NSLog需要#import <Foundation/Foundation.h>,里面有NSLog函數(shù)的聲明。不需要刻意記憶,想不起來,就編譯,出錯就會提示缺少什么。
4、可以只包含框架的主頭文件,效果等價包含了這個框架里的所有的頭文件。頭文件在Xcode里面,路徑很深,不好找。使用printf需要#include <stdio.h>
#import的作用(預處理)
1、跟#include一樣,用來拷貝某個文件的內(nèi)容
2、可以自動防止文件內(nèi)容被拷貝多次,也就是頭文件中不用和C一樣,加入下面的預處理指令了
#ifndef xxx xxx#define xxx xxx#endif
Foundation框架的作用
開發(fā)iOS、Mac程序必備的框架,此框架中包含了很多常用的API。框架中包含了很多頭文件,若想使用整個框架的內(nèi)容,包含它的主頭文件即可
#import <Foundation/Foundation.h>
相當于#include 導入頭文件 也有兩種查找方式< ... > 和" ... "。
當包含一個頭文件,編譯時,需要找到那個頭文件,使用< >這種方式,編譯器查找的時候,會在編譯器的安裝目錄的標準庫中開始查找," "這種方式,會在當前的工程所在的文件夾開始尋找,也就是源程序所在的文件夾。有的編譯器,要求十分嚴格,不能混用,有的就可以。
BOOL的使用(完全可以當做整型用)
BOOL類型的本質:
typedef signed char BOOL;
BOOL類型的變量只有兩種取值:YES、NO
#define YES (BOOL)1#define NO (BOOL)0
BOOL的輸出(當做整數(shù)來用);
NSLog(@"%d %d", YES, NO);//1 0
C里沒有布爾類型,c++,java里有,oc也有。不過oc的布爾和c++有區(qū)別,在C++里一切非 0 值的東西都為 true,而為0值的為false。但是Object-c里必須是1為 true ,且并被宏定義為 YES,0 為 false 并被宏定義為 NO。
所以下面的代碼,則肯定是得不到想要的運行順序。
1 #import <Foundation/Foundation.h> 2 BOOL isBool(int, int); 3 4 int main(void) 5 { 6 if (isBool(5, 1) == YES) { 7 NSLog(@"ok"); 8 } 9 return 0;10 }11 BOOL isBool(int x, int y)12 {13 return x - y;14 }
4不是1,在oc里永遠都不會等于YES(因為 oc 中的YES就是1),注意:BOOL大寫,YES 和 NO 也是大寫,OC 里的YES就是1,NO就是0
多個.m文件的開發(fā)和混合開發(fā)
跟C語言中多文件的開發(fā)是一樣的,回憶c多文件開發(fā),常量的定義或者函數(shù)的聲明寫在xxx.h文件,函數(shù)的定義寫在xxx.c文件,主文件main.c里寫主程序和函數(shù)調(diào)用,最后#include xxx.h文件,一起編譯主文件main.c和xxx.c文件即可。
面向對象常用術語
1) 類相當于圖紙,用來描述一類事物。
2) 利用類來創(chuàng)建對象,對象是類的具體存在
3) 因此,面向對象解決問題應該是先考慮需要設計哪些類,再利用類創(chuàng)建多少個對象
定義OC的類和創(chuàng)建OC的對象
定義一個新類分為 2 部分:
@interface 部分;
描述類、類的數(shù)據(jù)成分以及類的方法
@implementation 部分;
實現(xiàn)這些方法的實際代碼
@interface 部分的一般格式:
@interface NewClassName : ParentClassName{memberDeclarations;}methoddeclarations;@end
@implementation 部分的一般格式:
@implementation NewClassNamemethodDefinitions;
@end//NewClassName 表示的名稱與@interface 部分的類名相同
要描述類分2大步驟:類的聲明、類的實現(xiàn)(定義)。
跟函數(shù)類似,函數(shù)也分聲明和定義。而聲明一個類又需要三大要素:類名,屬性,行為,類似 c++。
命名規(guī)則:
以字母或下劃線開頭,之后可以是任何字母,下劃線或者0~9 數(shù)字組合。
約定:
類名以大寫字母開頭,命名有意義、比如駝峰標識。
實例變量、對象以及方法的名稱以小寫字母開始。每次創(chuàng)建新對象時,將同時創(chuàng)建一組新的實例變量且唯一。
注意:在對象類型的右邊都有一個 *號,所有的對象變量都是指針類型。
id (萬能指針)類型已經(jīng)被預定義為指針類型,所以不需要加一個*號。
三要素:方法名,參數(shù),返回值(類似函數(shù),分聲明和實現(xiàn)),方法的聲明在類的聲明里,且不能寫在花括號里。
方法雖然類似c的函數(shù),但是和函數(shù)千差萬別
只要方法是對象的方法,則聲明前必須加一個減號-,這是規(guī)則!
oc方法里的任何數(shù)據(jù)類型都必須用小括號()括起來
oc方法的小括號就一個作用,就是括住數(shù)據(jù)類型的。故- (void) run();是不對的!
類的實現(xiàn),類似于類的聲明語法,也要寫@end
對象里的成員變量,可以取值整型的,那么默認初始化為0
oc方法的實現(xiàn),必須寫在類的實現(xiàn)里,說清楚方法里有什么。
方法開頭的(-)號或者(+)號表示:
(-) 該方法是實例方法(對類的特定實例執(zhí)行一些操作) ;
(+)是類方法(即對類本身執(zhí)行某些操作的方法,例如創(chuàng)建類的新實例)
oc 一般的方法的聲明示例:
-(void)setNumerator :(int)n
第一個表示方法類型(對象方法-),返回類型(空void),接著是方法名(包括冒號:),方法接受的參數(shù)類型int和參數(shù)名n
注:如果不帶參數(shù)則不用使用“:”號
如果沒有指定任何返回類型, 那么默認是id類型, 所有的輸入?yún)?shù)默認也是id類型 (id類型可用來引用任何類型的對象,屬于萬能指針類型) 。
oc 里具有多個參數(shù)的方法聲明示例:
-/+ (return type) function_name : (parameter type) parameter1 otherParameter : (parameter_type) parameter2;
如果只有一個參數(shù),在: 后面聲明參數(shù)的類型和名稱
如果有多個參數(shù)的話,每個參數(shù)前面都要有一 個 :,接著是參數(shù)類型和參數(shù)名稱。
在 objective c 中,對于有多個參數(shù)的函數(shù),可以理解為將函數(shù)的名稱拆 成了幾個部分,每個部分都是對緊接著的參數(shù)的一個解釋 ,非常方便,做到見名知意,oc 官方文檔也是,尤其帶多個參數(shù)的方法名字往往特別的長。
如在 C++中多個參數(shù)的方法聲明:
void initializeRectangle(int x1, int y1, int x2, int y2);
但并不知道這些參數(shù)都是什么意思,但在objective-c 中,可以這樣聲明:
void initializeRectange: (int)x1 LeftUpY :(int)y1 RightBottomX: (int)x2 RightBottomY:(int)y2;
利用類創(chuàng)建對象
oc里,想執(zhí)行一些行為,必須寫上一個中括號[],方括號左面是類的名稱或者該類實例的名稱,空格后面是方法(即消息)
[classOrInstance method];
執(zhí)行Car這個類的new行為來創(chuàng)建對象,分配了內(nèi)存,每個對象都有自己的存儲空間來存儲自己的成員變量等元素
youCar = [Car new];//創(chuàng)建了一個Car類的對象,返回對象的地址(返回對象)。之后內(nèi)存里存在這個對象了。
oc里想操作對象,只能用指針去間接操作!
Car *p = [Car new];//把地址保存到指針里,p指向的是Car類型的對象
給p指向的對象的屬性賦值
p->speed = 200;
內(nèi)存分析(對象在內(nèi)存中有成員)
[Car new]每次都會創(chuàng)建出新的對象,并且返回對象的地址,那么就應該用一個指針變量保存對象的地址
Car *c = [Car new];//用一個指針變量c指向內(nèi)存中的Car對象
設置車子對象的屬性,跟用指向結構體的指針訪問結構體屬性一樣,用->
c->wheels = 3;
c->speed = 300;
對象在內(nèi)存里的變化和狀態(tài)圖
oc 類成員的訪問屬性:
oc類屬性,默認是@protected,本類內(nèi)部和繼承的類能訪問,而外部無法訪問,需要手動設置為public。
@pubic
有一個典型的錯誤
oc千萬不能想當然的和c++,java混淆,不用在類實現(xiàn)里再添加花括號了,直接寫方法的實現(xiàn)即可。
和c++的不同,oc的類占據(jù)一份內(nèi)存空間!
在第一次使用類的時候,類被加載到內(nèi)存里,即在創(chuàng)建對象之前,先給類分配內(nèi)存空間。
1、存放類的內(nèi)存只被加載一次(第一次使用對象的時候,加載對象屬于的類)即可,且里面只存放方法的列表。
2、內(nèi)存里每個類的對象的存儲空間內(nèi)部,默認都有一個指針叫isa指針,每個對象都有,作用是:指向這個對象所對應的類(存放類的內(nèi)存塊,幫助找到對象所屬的類),所以所有的對象都共用一份方法,所以類只被加載一次即可。成員變量每個對象都有自己的那一份內(nèi)存,但是方法就共用一份內(nèi)存
3、調(diào)用方法的過程:
[person1 walk];
執(zhí)行:
給指針person1指向的對象發(fā)送一條walk消息,去調(diào)用那個對象的walk方法,然后對象會順著isa指針找到對應的類,去類里找方法,找到walk方法,就前往對應的代碼去執(zhí)行,就在walk方法里訪問當前對象的成員變量age和weight(因為成員變量,每個對象都有自己的一份)
再次強調(diào):將對象賦給id類型變量不會有問題。
注:無論在哪里,對象總是攜帶它的isa的保護成員(一個指針,可以用來確定對象所屬的類) ,所以即使將它存儲在id類型的通用對象變量中,也總是可以確定它的類 。
|
新聞熱點
疑難解答