最近開始學習object-c,分享一下學習oc的經驗以及對oc的理解,其中難免會有錯誤,請大家理解。
對初學者來說,objective-c存在了很多令人費解的寫法,當然也包括我!
我剛開始看oc的代碼的時候:這是什麼東西,怎麼這麼多中括號,還有一堆“+”,“—”號是什麼東西,不是說好的c的超集,怎麼完全看不懂!
然後慢慢了解發現:哦,用法還是那樣子嘛!
下面我們開始學習oc。
object-c與c一樣,文件分爲頭文件和源文件,擴展名分別爲.h和.m。.h表示頭文件。頭文件包涵類的定義、類型、方法以及常量的聲明
.m表示源文件。這個典型的擴展名用來定義源文件,可以同時包含c和object-c的代碼。
我們先來看一段代碼:
//類的聲明 @interface Student : NSObject { NSString *studentName; NSInteger age; id: birthday; } -(Student*) initWithNameAndAge:(NSString*) name setAge:(NSInteger) age; -(void) printInfo; -(void) setStudentName: (NSString*) name; -(void) setAge: (NSInteger) age; -(NSString*) studentName; -(NSInteger) age; @end //類的實現 @implementation Student -(Student*) initWithNameAndAge:(NSString*) name setAge:(NSInteger) age { self = [super init]; if ( self ) { [self setNameAndAge:name setAge:age]; } return self; } -(void) printInfo { NSLog(@"姓名:%@ 年齡:%d歲",studentName,studentAge); } -(void) setStudentName: (NSString*) name { studentName = name; } -(void) setAge: (NSInteger) age { studentAge = age; } -(NSString*) studentName { return studentName; } -(NSInteger) age { return studentAge; } @end //調用 Student *student = [[Student alloc]init]; [student setStudentName:@"張三"]; [student setAge:10]; [student printInfo]; [student release]; |
@符號,可以把它看成是C語言的擴展。@interface是類的聲明,直到@end結束。其中Student是類名,冒號後面的NSObject父類。
關於oc中類的繼承:它不支持多繼承,如果要實現多繼承的話,可以通過類別和協議的方式來實現。
在花括號中間聲明瞭3個實例變量,分別是NSString,NSInteger以及id類型,其中id是object-c新加的一個數據類型,它可以代表任何類型。
我們發現,在對象類型的右邊都會有一個*號,是因爲在oc中,所有的對象變量都是指針類型。但是id類型已經被預定義爲指針類型,所以不需要加上“*”;
後面是方法的定義。一個方法定義包含了方法類型,返回類型,一個或者多個關鍵詞,參數類型和參數名。
在object-c中一個類中的方法有兩種類型:實例方法,類方法。實例方法前用(-)號表明,類方法用(+)表明。
如果有多個參數,如下方法定義:
-(void) myFunction: (NSString *)param1 secondParam: (NSString *) param2 thirdParam: (NSString *) param3;
可以理解爲(方法的數據類型) 函數名: (參數1數據類型) 參數1的數值的名字 參數2的名字: (參數2數據類型) 參數2值的名字 …. ;
接下來是類的實現。類的實現是從@implementation開始到@end結束。
oc中調用方法的寫法和c的的差異也非常大。
[[Student alloc]init]這句代碼用來定義一個對象,alloc是指分配內存,init是指初始化,也可以用new關鍵字來定義對象,如:[Student new]。
但是我們最好還是使用第一種方法,爲什麼呢?因爲使用第一種方法,你可以使用自己定義的init方法來做一些初始化。比如initWithNameAndAge方法。
在initWithNameAndAge方法中,self = [super init]是要求父類做(父類的)初始化操作。後面的if語句的作用是在嘗試設置(本對象的)缺省值之前驗證父類是否初始化成功。
我們調用一個類或實例的方法,也稱爲給這個類或實例發消息。類的實例稱爲“接收方”。所以,通用方法調用的格式也可以理解爲: [接收方 消息]。
[student release]是指在使用完student對象後釋放student的內存空間。
這是對以上代碼的講解。當然,oc的知識點不可能再上邊代碼中完全展示,那麼我們來看看其他的oc的知識:
1.在oc裏,包含頭文件有比#include更好的方法#import。它的使用和#include相同,並且可以保證你的程序只包含相同的頭文件一次。相當於c中的#include+ #pragma once的組合。
2.在oc中,bool類型的定義如下:
typedef signed char BOOL; #define YES (BOOL) 1 #define NO (BOOL) 0 |
可以看出,其實bool也是 char類型,其中yes代表1,no代表0.
3.在oc中, 所得的實例變量默認都是私有的。
4.協議是oc中一個非常重要的語言特性,從概念上講,相當於c++中的純虛類的概念。
一個協議其實就是一系列有關聯的方法的集合。
協議中的方法並不是由協議本身去實現,相反而是由遵循這個協議的其他類來實現。換句話說,協議只是完成對協議函數的聲明而並不管這些協議函數的具體實現。
//協議的聲明 @protocol myProtocol <NSObject> @required -(void) protocolNameA:(NSString*)string; @optional -(void) protocolNameB:(NSString*)string; @end |
協議的聲明是從@protocol到@end結束。
上面協議的名字爲myProtocol。尖括號中的NSObject本身也是一個協議,其中定義了很多基本的協議函數。
協議接口分爲required和optional兩類。
required顧名思義是說遵守這個協議的那個類“必須要”實現的接口,而optional則是可以實現也可以不實現的。協議接口的定義和普通的函數定義是一樣的。
//定義一個類遵循這個協議 @interface myClass <myProtocol> @interface myClass :NSObject<myProtocol> @interface myClass :NSObject<myProtocol, NSCoding> |
上面分別是三種不同的情況。編譯的時候編譯器會自動檢查myClass是否實現了myProtocol中的必要的(@required)接口。
如果沒有實現則會發出一個警告信息。另外需要注意的是,如果有繼承自myClass的子類,這些子類也是會自動遵循myClass所遵循的協議的,而且也可以重載這些接口。
5.委託是一種對象,另一個類的對象會要求委託對象執行它的某些操作。
套用最通俗的一句解釋:B需要完成一個操作,但他自己並沒有實現這個操作,而是交給了A去完成。
看如下代碼:
A_View.h:
@interface AViewController : UIViewController < UIBViewDelegate > { BView *m_BView; } @end |
A_View.m
- (void)viewWillAppear:(BOOL)animated { m_BView._touchdelegate = self; //設置委託 [self.view addSubview: m_BView]; } - (void)ontouch:(UIScrollView *)scrollView { //實現協議 } |
B_View.h:
@protocol UIBViewDelegate <NSObject> @optional - (void)ontouch:(UIScrollView *)scrollView; //聲明協議方法 @end @interface BView : UIScrollView<UIScrollViewDelegate> { id< UIBViewDelegate > _touchdelegate; //設置委託變量 } @property(nonatomic,assign) id< UIBViewDelegate > _touchdelegate; @end |
B_View.m
@synthesize _touchdelegate; - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // Initialization code } return self; } - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { [super touchesBegan:touches withEvent:event]; if(_touchdelegate!=nil && [_touchdelegate respondsToSelector: @selector(ontouch:) ] == true) [_touchdelegate ontouch:self]; //調用協議委託 } @end |
對於以上代碼的解釋,簡單來說就是在b view中首先定一個協議,然後設置一個委託變量,在a view實現協議中的方法。
然後把b view的委託變量設置成a view(即b view委託a view辦事情),事件發生後,用委託變量調用a view中的協議方法