我第一次看OC以爲這個語言的語法有些怪異,爲何充滿了@符號,[]符號,函數調用沒有()這個,可是面向對象的高級語言也不外乎類,接口,多態,封裝,繼承等概念。下面會把OC裏面的一些定義與Java,C++做對比,讓有其餘面嚮對象語言的同窗能夠快速的瞭解OC是個神馬語言。html
類用@interface定義,而不是@class,至關於Java中的class了。而Object-C中接口(Java中的接口)是用@protocol(下面有介紹)表示。java
頭文件,與c++的頭文件相似ios
1 #import <Foundation/Foundation.h> 2 @interface Fraction : NSObject 3 //成員變量 4 { 5 @protected 6 int numerator; 7 int denominator; 8 } 9 //類方法 10 -(void) print; 11 //多參數函數 12 -(id)initSetNum:(int) n over:(int) d; 13 -(id) init; 14 @end
實現.m文件(至關於c中的.cpp)c++
1 #import "Fraction.h" 2 3 @implementation Fraction 4 5 -(void) print { 6 NSLog(@"print"); 7 } 8 9 -(id)init{ 10 self = [super init]; 11 if (self != nil) { 12 self->denominator = 1; 13 self->numerator = 1; 14 } 15 return self; 16 } 17 -(void)set:(int)n over:(int)d { 18 self->denominator = d; 19 self->numerator = n; 20 } 21 22 @end
1 -(id)init{ 2 self = [super init]; 3 if (self) { 4 //do init 5 } 6 return self; 7 }
@property只在@interface中使用,是默認的@protected權限數組
方法的做用域xcode
@protected,@private,@public,@package不適用實例方法,在@interface中定義的方法都是@public方法多線程
語法app
@property(attribute1, attribute2, ...) type name;框架
1 @interface Fraction : NSObject 2 @property int numerator, denominator; 3 -(void)print; 4 @end
1 @implementation Fraction 2 @synthesize numerator = _abc, denominator = _def; 3 4 -(void) print { 5 self->_abc = 12; 6 self->_def = 30; 7 } 8 @end
1 #import <Foundation/Foundation.h> 2 #import "Fraction.h" 3 4 int main(int argc, const char * argv[]) { 5 @autoreleasepool { 6 // insert code here... 7 Fraction * fraction = [[Fraction alloc]init]; 8 [fraction setNumerator:10]; 9 NSLog(@"numerator is %d", [fraction numerator]); 10 11 fraction.numerator = 20; 12 NSLog(@"numerator is %d", fraction.numerator); 13 } 14 return 0; 15 }
@property int numerator, denominator;函數
@synthesize numerator = _abc, denominator = _def;
兩句話爲咱們生成了(暫時不考慮內存管理)
1 (void) setNumerator:(int) n { 2 //@synthesize numerator, denominator; 如果這樣則 3 //self->numerator = n; 4 self->_abc = n; 5 } 6 7 (void) setDenominator:(int) n { 8 self->_def = n; 9 } 10 11 (int) numerator { 12 return self->_abc; 13 } 14 15 (int) denominator { 16 return self->_abc; 17 }
若寫@synthesize name,則至關於寫了@synthesize name = name
oc的點語法比較特殊,c++或java定義一個實例變量,則能夠this->num或instance.num就能夠取得次變量了,可是oc不行!點至關於調用set和get方法,而且oc中的實例方法調用也不能用點(get set不算),好比instance.print()是不行的,要[instance print]才行
attribute主要分三類:
readwrite: 生成setter/gettter方法(默認)
readonly: 只生成getter。@synthesize不會生成setter方法,因此不能和copy/retain/assign同時使用
assign: 簡單賦值,不更改索引計數
retain: 釋放舊的對象,將舊對象的值賦予輸入對象,在增長輸入對象的引用計數(+1)。此屬性只能用於Objective-c對象類型,不能用於基本類型和Core Foundation對象(Core Foundation?此乃何物),由於他們沒有引用計數
strong/weak/unsafe_unretained: xcode5加入的新屬性,strong = retain,unsafe_unretained = assign,weak ~= assign,在引用計數爲0時,對吧對象賦值爲nil
copy: 創建一個引用計數爲1的對象,而後釋放舊對象。此屬性只對實現了NSCopying的對象類型有效
atomic/nonatomic: setter和getter是否是原子操做,若是是atomic則在多線程狀況下,setter和getter中不會被阻塞(切換線程)
這個概念在c++和java我找不到對應的概念,算是oc特性了
在一個類已經定義好了的狀況下,又想向類中增長一些新方法,可是有不想改原來的實現文件,或是找不到實現文件,這就是分類發揮做用的時候了,好比想在Fraction類中增長-(void)double方法,用分類能夠這麼搞
MathOps.h文件
1 #import "Fraction.h" 2 @interface Fraction(MathOps) 3 -(void)double; 4 @end
MathOps.m文件
1 #import "Fraction.h" 2 @implementation Fraction(MathOps) 3 -(void)double { 4 [self numerator] = [self numerator] * 2; 5 } 6 @end
這樣就能夠在Fraction的實例上使用[fraction double];了
類擴展(extension)是category的一個特例,有時候也被稱爲匿名分類。他的做用是爲一個類添加一些私有的成員變量和方法。
類實例的擴展只能在未命名分類中定義,在命名分類中是不容許的,而且要寫在響應的.m文件中
1 #import "Fraction.h" 2 @interface Fraction() //括號裏是空就是了 3 { 4 int MaxNum; 5 } 6 7 @property int minNum; 8 9 @end
Objective-C第229頁說,未命名分類是很是有用的,由於他們的方法都是私有的,若是要謝一個類,並且數據和方法僅供這個類自己使用,未命名分類比較合適,可是使用@selector依然能夠訪問,例如[A performSelector: @selector(privateTest)];
協議有點像java中的接口,只提供方法的聲明,實現由使用此協議的類來實現
1 @protocol NSCopying 2 -(id)copyWithZone:(NSZone *)zone; 3 @end
採用協議的類用<protocolName1,protocolName,...>來聲明採用了protocolName協議
@interface className: NSObject
協議中的方法類中不用所有實現,@optional後的方法不必定要實現,@required或默認的方法必定要實現
1 @protocol Drawing 2 -(void)paint; //採用的類中必須實現 3 -(void)erase; //採用的類中必須實現 4 @optional 5 -(void)outline; //採用的類中不必定實現 6 @required 7 -(void)showDetail; //採用的類中必須實現 8 @end
能夠在聲明對象時候指明它採用的協議,這樣在賦值時由編譯器檢查被複制對象是否採用了協議,若沒有則發出警告
id<Drawing> currentOBject;
協議自身也能夠擴展其餘的協議 @protocol Drawing3D<Drawing>
分類也能夠採用協議 @interface Fraction(Stuff)這是啥??
框架是由許多類、方法、函數和文檔按照必定的邏輯組合起來的集合,在Mac OS X系統下大約有90多個框架。
爲全部的程序開發奠基基礎的框架稱爲Foundation框架,它容許使用一些結拜的對象,如數字和字符串,一些對象集合,如數字、字典和集合。其餘功能包括處理日期和時間、自動化的內存管理、文件系統等。
Application Kit框架包含普遍的類和方法,它們用來開發交互式的圖形應用程序,使得開發文本、菜單、工具欄、表、窗口之類的過程變得十分簡便(Application Kit開發Mac app,UIKit開發手持IOS ap)。術語Cocoa Touch是指Foundation、Core Data和UIKit框架。術語Cocoa是指Foundation、Core Data、Application Kit框架。
1 NSArray * name = [NSArray arrayWithObjects:@"zhangsan", @"lisi", @"dawang", nil]; 2 3 NSMutableArray * nameMutable = [NSMutableArray array]; 4 for (int i = 0; i < 10; i++) { 5 nameMutable = [NSNumber numberWithInteger: i]; 6 }
1 CGPonit myPonit; 2 NSValue * ponitObj; 3 NSMutableArray * touchPoints = [NSMutableArray array]; 4 5 myPonit.x = 100; 6 myPoint.y = 200; 7 8 pointObj = [NSValue valueWithPoint:myPint]; 9 [touchPoints addObject: pointObj]; 10 11 myPoint = [[touchPoints lastObject]pointValue];
1 NSMutableDictionary * glossary = [NSMutableDictionary dictionary]; 2 3 [glossary setObject:@"zhangSan" forKey:@"zhang"]; 4 [glossary setObject:@"zhaoSi" forKey:@"zhao"]; 5 6 NSLog(@"name zhang is: %@", [glossary objectForKey:@"zhang"]); 7 8 NSDictionary * glossaryDic = 9 [NSDictionary dictionaryWithObjectsAndKeys: 10 @"zhangSan", @"zhang", 11 @"zhaoSi", @"zhao", 12 nil]; 13 14 for (NSString * key in glossaryDic) { 15 NSLog(@"%@:%@", key, [glossary objectForKey: key]); 16 }
ARC(Automatic Reference Counting)自動引用計數(神馬是引用計數自行腦補)。Xcode 4.2版本以後加入的新特性。Xcode4.2以前的內存管理要內存要當心的處理引用計數,retain,release,autorelease在代碼中隨處可見。
XCode4.2以後的ARC是在編譯的時候由編譯器在代碼中添加retain,release,autorelease代碼,程序要要作的就是開啓ARC(默認開啓)功能,在@property屬性參數中聲明號strong,weak等屬性就好了(定義變量時也能夠用strong,weak等)。開啓ARC後不能使用retain,release,編譯不經過。
任何在@autoreleasepool{}中定義的變量都是autorelease的,在出@autoreleasepool{}做用域時,會對其中的變量作一次release操做。
Cocoa和IOS應用程序中也有這個@autoreleasepool{},也就是說Cocoa和IOS中的變量都是autorelease的,每幀循環後會對autoreleasepool中的對象作一次pop操做,把對象從autoreleasepool中刪除,並作一次release。Objective-C Autorelease Pool 的實現原理這個介紹了ios中的autorealeasepool
NSLog添加了%@這麼一個輸出格式,%@對應的對象在編譯後會被替換爲對descriptionWithLocal方法的調用,若是此方法不存在,則替換爲description方法的調用 。
SEL 類成員方法的指針
能夠理解 @selector()就是取類方法的編號,他的行爲基本能夠等同C語言的中函數指針,只不過C語言中,能夠把函數名直接賦給一個函數指針,而Object-C的類不能直接應用函數指針,這樣只能作一個@selector語法來取.
它的結果是一個SEL類型。這個類型本質是類方法的編號(函數地址)
C/C++函數指針
int test(int val)
{
return val+1;
}
int (* c_func)(int val); //定義一個函數指針變量c_func = add ; //把函數addr地址直接賦給c_func
object-c的選擇器,
@interface foo
-(int)add:int val;
@end
SEL class_func ; //定義一個類方法指針class_func = @selector(add:int);
注意一、@selector是查找當前類(含子類)的方法。
舉例:
父類.h文件
1 #import <Foundation/Foundation.h> 2 3 @interface SelectorDemo : NSObject 4 { 5 SEL _methodTest; 6 } 7 8 @property (nonatomic,assign) SEL methodTest;//這裏聲明爲屬性方便在於外部傳入。 9 10 -(void)TestParentMethod; 11 12 -(void)TestSubMethod; 13 14 15 @end
.m文件
1 #import "SelectorDemo.h" 2 3 @implementation SelectorDemo 4 5 @synthesize methodTest = _methodTest; 6 7 -(void)parentMethod 8 { 9 NSLog(@"parent method Call Success!"); 10 } 11 12 -(void)TestParentMethod 13 { 14 if (_methodTest) 15 { 16 [self performSelector:_methodTest withObject:nil]; 17 } 18 } 19 20 -(void)TestSubMethod 21 { 22 if (_methodTest) 23 { 24 [self performSelector:_methodTest withObject:nil]; 25 } 26 } 27 28 @end
子類.h文件
1 #import <Foundation/Foundation.h> 2 #import "SelectorDemo.h" 3 4 @interface SelectorSub : SelectorDemo 5 6 @end
.m文件
#import "SelectorSub.h" @implementation SelectorSub -(void)SubMethod { NSLog(@"Sub method Call Success!"); } @end
進行測試調用。
SelectorSub *ss = [[SelectorSub alloc]init]; ss.methodTest = @selector(parentMethod); [ss TestParentMethod]; ss.methodTest = @selector(SubMethod); [ss TestParentMethod]; [ss release];
ss.methodTest = @selector(parentMethod); 這句在運行期時,會尋找到父類中的方法進行調用。
ss.methodTest = @selector(SubMethod);//這句就在運行期時,會先尋找父類,若是父類沒有,則尋找子類。
若是這裏將ss.methodTest = @selector(test); 其中test即不是ss父類,也不是ss自己,也非SS子類,哪麼這個時候在使用
[self performSelector:_methodTest withObject:nil];就會出現地址尋找出錯 。
[friend performSelector:@selector(gossipAbout:) withObject:aNeighbor];
等價於:
[friend gossipAbout:aNeighbor];
經過這個原理,當把屬性設置爲SEL類型時,若是回調機制使用的不是SEL聲明的類或子類。想實現其它類的回調,必須傳入其它類的上下文句柄。
#import <Foundation/Foundation.h> @interface SelectorDemo : NSObject { SEL _methodTest; id _handle; } @property (nonatomic,assign) SEL methodTest; @property (nonatomic,retain) id handle; //添加其它類的實例句柄屬性。 -(void)TestParentMethod; -(void)TestSubMethod; @end
#import "SelectorDemo.h" @implementation SelectorDemo @synthesize methodTest = _methodTest; @synthesize handle = _handle; -(void)parentMethod { NSLog(@"parent method Call Success!"); } -(void)TestParentMethod { if (_methodTest) { [_handle performSelector:_methodTest withObject:nil];//這裏面原來self屬爲相應的實例句柄 } } -(void)TestSubMethod { if (_methodTest) { [_handle performSelector:_methodTest withObject:nil]; } } @end
即可如此調用
C * c = [[SubS alloc]init]; c.methodTest = @selector(Show); c.handle = [[AnotherC alloc]init]; [c handleTest];
有參數有返回值的demo
1 - (void)myThirdBlock 2 { 3 //1.定義block 4 double (^myThirdBlock)(double,double) = ^ (double r1,double r2){ 5 return r1 + r2; 6 }; 7 //2.調用block 8 double r3 = myThirdBlock(1.1,2.2); 9 NSLog(@"有參數有返回值:%f",r3); 10 }
block的注意點
1)Block內部能夠訪問外部變量;
2)默認狀況下,Block內部不能修改外部的局部變量
3)給局部變量加上__block關鍵字,則這個局部變量能夠在block內部進行修改
示例代碼以下:
1 - (void)myFourBlock 2 { 3 int num = 5; 4 void (^myFourBlock)() = ^{ 5 6 num = 6; 7 NSLog(@"%d",num); 8 }; 9 }
//發現須要的再加
本博介紹了OC的核(pi)心(mao)概念,但願看完本博能夠對讓你對OC有一個大致的認識,學OC是學ios的第一步, 打下堅實的OC仍是很必要的。