读《Objective-C培训资料》的摘要

#definenilNULL

bool型与c/c++是一样的,非0为TRUE/YES,0为FALSE/NO,用if(flag==YES)就要注意了,此时YES就是1,不过你直接用if(flag).....来判断就只要不是0就成立。

#import和c/C++的include一样也有<>和""两种查找方式。但是它不怕重复引入。

NSLog()会自动在输出后加\n,相当于System.out.println().

Objective-C的对象需要直接或间接的继承自NSObject。Objective-C的@interface相当java的class,而@protocol才是Java的interface。类声明的基本方式如下:

@interface<#class#>:<#superclass#>

{

<#ivars#>

}

<#methods#>

@end

@implementation<#class#>

<#methods#>

@end

(-)表示实例方法

(+)是类方法,即静态方法

函数的形式是:-(void)setNum:(int)n;

多个参数用-(void)setNum:(int)n:(int)m;用[carsetNum(1:3)];调用

或者给第一个之后的参数指定参数名,如

-(void)setNum:(int)nandHeight:(int)handWidth:(int)w;用[carsetNum:1andHeight:5andWidth:10];

Objective-C的方法参数有点怪异,第一个参数是没有参数名的,如果硬要说有,那就是方法名,统一说来,见到冒号,冒号前面那个就是参数名

没有指定返回类型就是id类型,输入参数默认也是id类型。

实例化:

Car*car=[[Caralloc]init];或Car*car=[Carnew];通常用前一种。

释放对象[carrelease];iPhone平台不支持垃圾回收机制。

#define和C的一样

数据声明及初始化intPtr=(int[100){[0]=1,[50]=50,[51]=200};

intnumber;

scanf("%i",&number);

NSLog(@"Numberis:%i",number);

输入

@protected@private$public@package修饰变量,voaltile和const

所有方法都是public的,私有方法该如何声明呢?

NSString和NSMutableString一个是不可变,一个是可变的,相应的有NSArray和NSMutableArray.

NSLog(@"StringHERE%@",@"Helloworld.");

[objectretain][objectrelease]分别使引用计数加1和减1。

NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];

RetainTracker*tracker;

tracker=[RetainTrackernew];//count:1

[trackerretain];//count:2

[trackerautorelease];//count:still2

[trackerrelease];//count:1

NSLog(@"releasingpool");

[poolrelease];

//getsnuked,sendsreleasetotracker

当使用alloc、new或者通过copy消息(生成接受对象的一个副本)创建一个对象,对象的引用计数器被设置成1。发送retain消息将增加引用计数器,release消息减1。

不必费心地释放其他方法返回的对象,这不是你的责任

通常的写法:

-(id)init

{

if(self=[superinit]){

...

}

return(self);

}

注:在自己的初始化方法中,需要调用自己的指定的初始化函数或者超类的指定的初始化函数。一定要将超类的初始化函数的值赋给self对象,并返回你自己的初始化方法的值。超类可能决定返回一个完全不同的对象。

存取器(属性)的例子:

//Car.h文件

#import<Cocoa/Cocoa.h>

@interfaceCar:NSObject{

NSString*name;

}

@property(copy)NSString*name;//表明类的对象具有NSString*类型的name属性,表明可以调用-setName和-name方法,即相应的setter/getter方法

@end//Car

//Car.m文件

#import"Car.h"

@implementationCar

@synthesizename;//表示实际创建该属性的访问器,即-setName和-name方法

@end//Car

//*********************************************************************************

最后就可以在main()函数中使用点表示法给对象赋值

Car*car=[[Caralloc]init];

car.name=@"Herbie";//调用了setName方法

NSLog("%@",car.name);//调用了name方法

@property和@synthesize可同时指定多个。

@property(copy)intwidth,height;

@synthesizewidth,heigth;

该技术同样适用于int、char、BOOL、struct甚至可以定义一个NSRect类的对象的特性

@property(readwrite,copy)NSString*name;//对象可读写,对象将被复制

@property(readwrite,retain)NSString*name;//对象可读写,对象将被保持

@property(readonly)NSString*name;////对象只读

C/C++中支持的内存方式Objective-C都支持(例如new,delete或malloc,free),Objective-C也有自己对象分配内存的方法:alloc,allocWithZone。

Objective-C不支持多继承,可以通过Objective-C的分类和协议特性获取多继承的优点

@classXYPoint;//代替#import"XYPoint.h"

//使用@class指令提高效率,编译器不需要处理整个XYPoint.h文件,只需要知道XYPoint是一个类名,但是如果需要引用XYPoint类中方//法,@class指令是不够的,必须用#import"XYPoint.h"。

分类的应用:

#import<Foundation/Foundation.h>

@interfaceCar:NSObject

{

intc;

}

-(id)init;

-(void)toString;

@end

@implementationCar

-(id)init

{

if(self=[superinit])

{

c=100;

}

returnself;

}

-(void)toString

{

NSLog(@"YESid:%i",c);//分类后最原始的方法访问不到了

}

@end

//进行分类,类名与已有类名相同

@interfaceCar(Unmi)//括号中任意指定一个Category名

-(void)toString;

@end

@implementationCar(Unmi)

-(void)toString//分类方法的实现

{

NSLog(@"Categoryid:%i",c);//分类中的方法可以引用变量

}

@end

intmain(intargc,constchar*argv[]){

NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];

Car*car=[[Caralloc]init];

[cartoString];//这行的输出是Categoryid:100

[pooldrain];

return0;

}

关于分类的一些注意事项

A、尽管分类可以访问原始类的实例变量,但是它不能添加自身的任何变量。如果需要添加变量,可以考虑创建子类。

B、分类可以重载该类中的另一个方法,但是通常认为这种做法不可取。因为,重载之后,再不能访问原来的方法。

C、可以拥有很多分类。

D、和一般接口部分不同的是,不必实现分类中的所有方法。这对于程序扩展很有用,可以在该分类中声明所有方法,然后在一段时间之后才实现它。

E、通过使用分类添加新方法来扩展类不仅会影响这个类,同时也会影响它的所有子类。

@synthesizename=_name;的用法:

@interfaceCar:NSObject

@property(copy)NSString*name;

@end

@implementationCar

@synthesizename=_name;//这个的效果会同时声明一个_name实例变量,方便于内部操作

@end

上面相当于,声明了一个实例变量

@interfaceCar:NSObject

{

NSString*_name;

}

@property(copy)NSString*name;

@end

@implementationCar

@synthesizename;

@end

这样在实例方法中就可以直接引用_name,如

-(void)foo

{

_name=@"abc";

}

协议间也是可以相互继承的,并且不能定义成员变量,只能定义方法。protocol的声明方式:

@protocolMyProtocol

-(void)myProtocolMethod;

@end

应用协议的代码:

@interfaceCat:NSObject<myProtocol>;

可以应用多个协议

@interfaceCat:NSObject<myProtocol,myProtocol2>

应用了协议必须实现协议中定义的方法,虽然未实现协议中的方法编译能通过,但运行时会报错的:

2011-05-2415:05:35.065test[5781:a0f]-[CatmyProtocolMethod]:unrecognizedselectorsenttoinstance0x10010c6b0

2011-05-2415:05:35.083test[5781:a0f]***Terminatingappduetouncaughtexception'NSInvalidArgumentException',reason:'-[CatmyProtocolMethod]:unrecognizedselectorsenttoinstance0x10010c6b0'

有关协议的注意事项:

A、如果一个类遵守某项协议,那么它的子类也遵守该协议。

B、通过在类型名称之后的尖括号中添加协议名称,可以借助编译器的帮助来检查变量的一致性,如下:

id<Drawing>currentObject;//协议是不有点像泛型那么回事啊

这告知编译器currentObject将包含遵守Drawing协议的对象。如果向currentObject指派静态类型的对象,这个对象不遵守Drawing协议,编译器将给出warning。

再次提到id类型,如果向currentObject指派一个id变量,不会产生这条消息,因为编译器不知道存储在id变量中的对象是否遵守Drawing协议。

C、如果这个变量保存的对象遵守多项协议,则可以列出多项协议,如下:

id<Drawing,Drawing1>currentObject;

D、定义一项协议时,可以扩展现有协议的定义。以下协议

@protocolDrawing3D<Drawing>

说明Drawing3D协议也采用了Drawing协议。因此采用Drawing3D协议的类都必须实现此协议列出的方法,以及Drawing协议的方法。

E、分类也可以采用一项协议,如:

@interfaceFraction(stuff)<NSCopying,NSCoding>

此处,Fraction拥有一个分类stuff,这个分类采用了NSCopying和NSCoding协议。

在构建数组NSArray,用arrayWithObjects时最后一个元素需要是nil,即:

NSArray*array=[NSArrayarrayWithObjects:@"ab",@"cd",nil];

用对象的copy、mutableCopy可复制出对象。

Archive(归档),序列化与反序列化:对象是NSString、NSDictionary、NSArray、NSData、NSNumber对象时,可以使用writeToFile:atomically:方法将数据写到文件中,是以属性列表的形式写到文件中的。参数atomically为YES,表示先将数据写到临时备份文件中,一旦成功,再转移到文件中。

相应的,像dictionaryWithContentOfFile函当我可以从文件中读取序列化出对象来,

写出的文件内容格式,NSArray的样子是:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEplistPUBLIC"-//Apple//DTDPLIST1.0//EN"

"http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plistversion=”1.0”>

<array>

<string>I<string>

<string>seem<string>

<string>to<string>

<string>be<string>

<string>a<string>

<string>verb<string>

</array>

</plist>

NSDictionarywriteToFile的文件是:

<key>...</key>

<string>...</string>

读回数据还可以用的方法dataWithContentOfFile/stringWithContentOfFile/dictionaryWithContentOfFile/arrayWithContentOfFile

还有NSKeyedArchivers的archiveRootObject:toFile和unArchiveObjectWithFile

相关推荐