一 了解一下,找參考資料
1.看書學習object-c語法,第一本看的是《objective-c程序設計》。
二 定義類
1. 格式
object-c中定義類的方式和c#不同,它分為兩個部分,一般放在兩個獨立的文件中:
①在@interface部分聲明類,文件格式.h;
②在@implementation部分實現類,文件格式.m。
Fraction.h
#import <Foundation/Foundation.h>
@interface Fraction : NSObject
-(void)setAge:(int)age;
-(int)getAge;@end
以上代碼有幾點說明:
①NSObject是默認的父類;
②方法前面的負號(-)表示這是一個實例方法;如果是正號(+)表示這是一個類方法。
3. @implementation 部分
Fraction.m
#import "Fraction.h"
@implementation Fraction
{
int _age;
}
-(void)setAge:(int)age
{
_age=age;
}
-(int)getAge
{
return _age;
}@end
4.調用
注意:@autoreleasepool引入了自動計數處理內存釋放問題;看一下對象初始化和方法調用的格式。
main.m
#import <Foundation/Foundation.h>
#import "Fraction.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {//對象初始化
Fraction *fraction=[Fraction alloc];
fraction=[fraction init];//調用方法
[fraction setAge:100];
int age=[fraction getAge];//打印結果
NSLog(@"the age is %i",age);
}}
三 基本數據類型
1. 基本類型
object-c的幾種基本數據類型: int ,float,double,char
2.float類型
NSLog轉換字符為 %f或者%g
NSLog(@"The float result is %f",f);//The float result is 1.230000
NSLog(@"The float result is %g",f);//The float result is 1.23
3.字符串
用@開頭並且放在雙引號中的字符串是NSString字符串類型。
各類型的NSLog輸出轉換如下:
int main(int argc,const char* argv[]){
@autoreleasepool{
int a=100;
NSLog(@"the integer value is %i",a);
float f=1.23;
NSLog(@"The float result is %f",f);//The float result is 1.230000
NSLog(@"The float result is %g",f);//The float result is 1.23
double d=1.2345;
NSLog(@"The double value is %e",d);//The double value is 1.234500e+000
char c='V';
NSLog(@"The char value is %c",c);//The char value is V
}
return 0;}
4.id類型
id數據類型可以存儲任何類型的對象。id類型是多態和動態綁定的基礎。
5.布爾類型
objective-c中的布爾值是YES和NO.
int main(int argv,const char * argc[])
{
@autoreleasepool {
for(int i=2;i<=50;i++)
{
bool isPrime=YES;
for(int j=2;j<i;j++)
{
if(i%j==0)
{
isPrime=NO;
continue;
}
}
if(isPrime==YES)
{
NSLog(@"%i",i);
}
}
}
return 0;}
四 scanf和NSLog
scanf :接收輸入值,第一個參數始終是C風格的字符串,第二個參數用於指定用戶輸入的值儲存在哪里;
NSLog:輸出結果,第一個參數始終是NSString。
int main(int argc, const char * argv[])
{
@autoreleasepool {
int number;
NSLog(@"請輸入要計算的數值?");
scanf("%i",&number);
int result=0;
for(int i=1;i<=number;i++)
{
result+=i;
}NSLog(@"The Triangular number of %i is %i",number,result);
}
return 0;}
五 類
1 合成存取方法
所謂合成存取方法,就是自動設值和取值,類似於c#中的屬性。它的定義和使用步驟為:
①在 @interface 中使用 @property 標識屬性;
②在 @implementation 中使用 @synthesize 指令;
③調用屬性方法,可以使用傳統的方括號語法,也可以使用點運算符進行屬性讀寫。
Fraction.h
#import <Foundation/Foundation.h>
@interface Fraction : NSObject@property int number1,number2;
-(void)print;
@end
Fraction.m
#import "Fraction.h"
@implementation Fraction@synthesize number1,number2;
-(void)print
{
NSLog(@"number1 is %i,number2 is %i",number1,number2);}
@end
main.m
#import <Foundation/Foundation.h>
#import "Fraction.h"int main(int argc, const char * argv[])
{
@autoreleasepool {
Fraction *fraction=[Fraction alloc];
fraction=[fraction init];//調用方式1
[fraction setNumber1:10];
[fraction setNumber2:20];
[fraction print];
//調用方式2
fraction.number1=30;
fraction.number2=40;[fraction print];
}
}
2.多個參數的方法
例如我們想同時設置上述例子Fraction中的number1和number2的值,可以使用帶多個參數的方法。(說實話,第一次看到這個語法的時候尷尬症都犯了。)
Fraction.h
#import <Foundation/Foundation.h>
@interface Fraction : NSObject
@property int number1,number2;
-(void)print;
-(void)setNumber1:(int)n1 andNumber2:(int)n2;@end
Fraction.m
#import "Fraction.h"
@implementation Fraction
@synthesize number1,number2;
-(void)print
{
NSLog(@"number1 is %i,number2 is %i",number1,number2);
}
-(void)setNumber1:(int)n1 andNumber2:(int)n2
{
number1=n1;
number2=n2;
}@end
main.m
#import <Foundation/Foundation.h>
#import "Fraction.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Fraction *fraction=[Fraction alloc];
fraction=[fraction init];[fraction setNumber1:50 andNumber2:60];
[fraction print];
}}
3.方法帶引用類型的參數
Fraction.h
#import <Foundation/Foundation.h>
@interface Fraction : NSObject
@property int number1,number2;
-(void)print;
-(void)setNumber1:(int)n1 andNumber2:(int)n2;
-(void)add:(Fraction*)f;@end
Fraction.m
#import "Fraction.h"
@implementation Fraction
@synthesize number1,number2;
-(void)print
{
NSLog(@"number1 is %i,number2 is %i",number1,number2);
}
-(void)setNumber1:(int)n1 andNumber2:(int)n2
{
number1=n1;
number2=n2;
}
-(void)add:(Fraction *)f
{
number1+=f.number1;
number2+=f.number2;
}@end
main.m
#import <Foundation/Foundation.h>
#import "Fraction.h"
int main(int argc, const char * argv[])
{@autoreleasepool {
Fraction *f1=[[Fraction alloc] init];
Fraction *f2=[[Fraction alloc] init];
[f1 setNumber1:1 andNumber2:2];
[f2 setNumber1:3 andNumber2:4];
[f1 add:f2];
[f1 print];
}}
六 繼承
1. 繼承
我們所定義的類都是從NSObject繼承而來。
繼承實例: 在這個例子中Rectangle是父類,Square是子類。
XYPoint.h
#import <Foundation/Foundation.h>
@interface XYPoint : NSObject
@property int x,y;
-(void)setX:(int)x andSetY:(int)y;@end
XYPorint.m
#import "XYPoint.h"
@implementation XYPoint
@synthesize x,y;
-(void)setX:(int)xVal andSetY:(int)yVal
{
在這個例子中Rectangle是父類,Square是子類 x=xVal;
y=yVal;
}@end
父類:
Rectangle.h
#import <Foundation/Foundation.h>
#import "XYPoint.h"
@interface Rectangle : NSObject
@property int width,height;
-(void)setWidth:(int)w andSetHeight:(int)h;-(int)area;
-(void)setOrignal:(XYPoint *)original;
-(XYPoint *)original;
@end
Rectangle.m
#import "Rectangle.h"
@implementation Rectangle
{
XYPoint * _original;}
@synthesize width,height;
-(void)setWidth:(int)w andSetHeight:(int)h
{
width=w;
height=h;
}
-(int)area
{
return width*height;}
-(int)area
{
return width*height;
}
-(void)setOrignal:(XYPoint *)p
{
_original=p;
}
-(XYPoint *)original
{
return _original;}
@end
子類
Square.h
#import <Foundation/Foundation.h>
#import "Rectangle.h"
@interface Square : Rectangle
-(void)setSide:(int)s;
-(int)side;@end
Square.m
#import "Square.h"
@implementation Square
-(void)setSide:(int)s
{
[self setWidth:s andSetHeight:s];
}
-(int)side
{
return self.width;
}@end
main.m
#import "Rectangle.h"
#import "Square.h"
int main(int argc,const char * argv[])
{
@autoreleasepool {//父類
Rectangle *rectangle=[[Rectangle alloc] init];
[rectangle setWidth:5 andSetHeight:6];
NSLog(@"rectangle w=%i,h=%i,area=%i",rectangle.width,rectangle.height,[rectangle area]);//子類
Square *square=[[Square alloc] init];
[square setSide:8];
NSLog(@"square side=%i,area=%i",square.side,[square area]);}
return 0;
}
2.覆蓋
如果子類使用和父類相同的名稱定義的方法,可以覆寫父類中的方法。新方法必須具有相同的返回類型,並且參數的數目與覆寫方法完全一致。例如下面的例子中ClassB覆寫了ClassA的initVar方法。
ClassA.h
#import <Foundation/Foundation.h>
@interface ClassA : NSObject
{
int x;
}
-(void)initVar;
-(void)print;@end
ClassA.m
#import "ClassA.h"
@implementation ClassA
-(void)initVar
{
x=1;
}
-(void)print
{
NSLog(@"x=%i",x);
}@end
ClassB.h
#import <Foundation/Foundation.h>
#import "ClassA.h"
@interface ClassB : ClassA
-(void)initVar;@end
ClassB.m
@implementation ClassB
-(void)initVar
{
x=2;
}
@end
main.m
#import "ClassB.h"
int main(int argc,const char * argv[])
{
@autoreleasepool {
ClassB * b=[[ClassB alloc] init];[b initVar];
[b print];// x=2
}
return 0;}
七 id類型和動態綁定
1. id可以用來存儲屬於任何類的對象。
例如:
#import "Complex"
int main(int argc,const char * argv[])
{
@autoreleasepool {id d1=[[Complex alloc] init]; //Complex *c1=[[Complex alloc] init];
[d1 setReal:1 andImaginary:2];
id d2=[[Comlex alloc] init];
[d2 setReal:3 andImaginary:4];
[d1 print];
NSLog(@" +");
[d2 print];
NSLog(@"-------");
id d3=[d1 add:d2];
[d3 print];
}
return 0;}
注意,這里id類型的聲明中不使用星號。
為了盡量在編譯期間就識別到更多地錯誤,並且增強程序的可讀性,不要養成濫用id這種通用數據類型的習慣。盡量使用靜態類型和有意義的變量名來提高程序的可讀性。
八 捕捉異常
@try …@catch可以捕獲到程序中的異常,如下所示:
int main(int argc,const char * argv[])
{
@autoreleasepool {@try {
...
}
@catch (NSException *ex) {
NSLog(@"error name:%@ ;reason:%@",[ex name],[ex reason]);
}
@finally {
NSLog(@"done");
}
return 0;
}}
當出現異常時,會執行@catch代碼塊,參數NSException對象包含了異常的詳細信息,name方法返回異常的名稱,reason方法給出異常的詳細信息。
九 變量和數據類型
1.自定義對象的初始化方法
在前面的例子中,我們創建對象並且初始化都是這樣做的:
Complex *c1=[[Complex alloc] init];
[c1 setReal:10 andImaginary:20];
接下來我們自定義對象的初始化方法,一般也是以init開頭。
Complex.h
@interface Complex : NSObject
@property double real,imaginary;
-(void)print;-(void)setReal:(double)r andImaginary:(double) m;
-(Complex *)initWithReal:(double)r andImaginary:(double) m;
@end
Complex.m
#import "Complex.h"
@implementation Complex
@synthesize real,imaginary;
-(void)print
{
NSLog(@"%g + %gi",real,imaginary);
}
-(void)setReal:(double)r andImaginary:(double)m
{
real=r;
imaginary=m;}
-(Complex *)initWithReal:(double)r andImaginary:(double)m
{
self=[super init];
if(self)
{
[self setReal:r andImaginary:m];
}
return self;
}@end
main.m
#import "Complex.h"
int main(int argc,const char * argv[])
{@autoreleasepool {
Complex *c=[[Complex alloc] initWithReal:10 andImaginary:20];
[c print];}
return 0;
}
2.靜態變量
靜態變量定義在所有方法之外,使用static修飾符,它屬於類,而不屬於類對象。例如在下面的例子中,使用gCount變量記錄allocC調用次數。
Complex.h
#import <Foundation/Foundation.h>
@interface Complex : NSObject
@property double real,imaginary;
...
+(Complex *)allocC;
+(int)count;@end
Complex.m
#import "Complex.h"
static int gCount=0;
@implementation Complex...
+(Complex *)allocC
{
gCount++;
return [Complex alloc];
}
+(int)count
{
return gCount;
}@end
main.m
#import "Complex.h"
int main(int argc,const char * arg[])
{
@autoreleasepool {
NSLog(@"count=%i",[Complex count]);//0
Complex *c=[[Complex allocC] init];
Complex *c1=[[Complex allocC] init];
Complex *c2=[[Complex allocC] init];
NSLog(@"count=%i",[Complex count]);//3
}
return 0;}
十 分類和協議
1.分類
通過分類可以很簡單地向現有類添加方法,功能類似於C#的擴展方法。格式為: @interface Complex(MathOps)
例如:
①現有Complex.h定義:
#import <Foundation/Foundation.h>
@interface Complex : NSObject
@property double real,imaginary;
-(void)print;
-(void)setReal:(double)r andImaginary:(double) m;@end
Complex.m
#import "Complex.h"
//static int gCount=0;
@implementation Complex
@synthesize real,imaginary;
-(void)print
{
NSLog(@"%g + %gi",real,imaginary);
}
-(void)setReal:(double)r andImaginary:(double)m
{
real=r;
imaginary=m;}
@end
②現在想擴展Complex類,如下:
Complex+MathOps.h
#import <Foundation/Foundation.h>
#import "Complex.h"
@interface Complex(MathOps)
-(Complex *)add:(Complex *)c;@end
Complex+MathOps.m
#import "Complex+MathOps.h"
@implementation Complex(MathOps)
-(Complex *)add:(Complex *)c
{
Complex *result=[[Complex alloc] init];
result.real=self.real+c.real;
result.imaginary=self.imaginary+c.imaginary;
return result;
}@end
main.m調用:
#import "Complex.h"
#import "Complex+MathOps.h"
int main(int argc,const char * argv[])
{
@autoreleasepool {
Complex *c1=[[Complex alloc] init];
[c1 setReal:1 andImaginary:2];
Complex *c2=[[Complex alloc] init];
[c2 setReal:3 andImaginary:4];Complex *c3=[c1 add:c2];
[c3 print];//4 + 6i
}
return 0;}
這樣我們就為原有的Complex類新增了add方法。
2.協議
protocol定義一組方法,它是不屬於具體某個類的,可以被任意類實現,類似於C#中的接口interface。
①定義protocal
使用@protocol指令,后面跟上協議名稱,以@end指令結束。
例如:
MathProtocol.h
#import <Foundation/Foundation.h>
@protocol MathProtocol
-(id)add:(id)v;
@optional
-(id)subscribe:(id)v;@end
其中@optional指令表示其后面的方法是可選的。
②實現protocol
在@interface行使用尖括號<>,其中加上協議的名稱,然后在.m文件中實現協議中的方法即可。
Complex11.h
#import <Foundation/Foundation.h>
#import "MathProtocol.h"
@interface Complex11 : NSObject<MathProtocol>
@property int real,imaginary;
-(void)setReal:(int)r andImaginary:(int)m;@end
Complex11.m
#import "Complex11.h"
@implementation Complex11
@synthesize real,imaginary;
-(void)setReal:(int)r andImaginary:(int)m
{
real=r;
imaginary=m;
}
-(Complex11 *)add:(Complex11 *)v
{
Complex11 *result=[[Complex11 alloc] init];
result.real=self.real+v.real;
result.imaginary=self.imaginary+v.imaginary;
return result;
}@end
main.m
#import "Complex11.h"
int main(int argc,const char * argv[])
{
@autoreleasepool {
Complex11 *c=[[Complex11 alloc] init];
[c setReal:1 andImaginary:2];
Complex11 *c2=[[Complex11 alloc] init];
[c2 setReal:3 andImaginary:4];
Complex11 *result=[c add:c2];
NSLog(@"%i +%ii",result.real,result.imaginary);
//檢查是否遵循某項協議
bool isprotocol=[c conformsToProtocol:@protocol(MathProtocal)];
if(isprotocol==YES){
NSLog(@"c confirm protocol MathProtocol");
}
}
return 0;}
要想判斷一個對象是否遵守某項協議,可以使用confirmsToProtocol方法。