一 了解一下,找参考资料
1.看书学习object-c语法,第一本看的是《objective-c程序设计》。
2.官网:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html
二 定义类
1. 格式
object-c中定义类的方式和c#不同,它分为两个部分,一般放在两个独立的文件中:
①在@interface部分声明类,文件格式.h;
②在@implementation部分实现类,文件格式.m。
2.@interface 部分
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方法。
|
请发表评论