接上一篇:http://blog.csdn.net/kwiner/archive/2011/03/20/6263503.aspx
内存管理
在
Objective-C中,NSObject
定义了release和dealloc函数,一般来说,如果你的类中包含有对象,需要重载dealloc函数,在dealloc中释放类成员变量所占用的
内存,下面的代码演示了,当给一个对象发送release消息,或者这个对象被自动释放池回收时,dealloc会得到调用,这种行为使用dealloc
有点像C++中的析构函数。
为什么释放时用release而不是dealloc?原因是需要由release判断引用计数,当引用计数为0时release才会调用dealloc执行实际的释放内存操作。
文件 MyClass.h:
#import <Foundation/Foundation.h>
@interface MyClass: NSObject { } -(void) dealloc; -(void) release; +(MyClass*) createObj; @end |
文件 MyClass.m:
#import "MyClass.h"
@implementation MyClass -(void) release { NSLog(@"MyClass release"); [super release]; } - (void) dealloc { NSLog(@"MyClass dealloc"); [super dealloc]; } +(MyClass*) createObj { MyClass* pClass = [MyClass alloc]; /* 给返回值发送了autorelease消息,表示该函数的调用者不需要手动释放返回值所指向的对象,这个对象会由自动释放池自动释放。*/ return [pClass autorelease]; } @end |
文件 main.m:
#import <Foundation/Foundation.h>
#import "MyClass.h" int main( int argc, const char *argv[] ) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; MyClass* pClass = [MyClass createObj]; [pool emptyPool]; NSLog(@"exit."); [pool release]; return 0; } |
如上面的代码所示,可以使用自动释放池会释放内存,但是如果有一部分内存要立即释放,即可以嵌套另一个自动释放池来实现,如下面的示例所示:
int main (int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int i, j; for (i = 0; i < 100; i++ ) { NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; for (j = 0; j < 100000; j++ ) [NSString stringWithFormat:@"1234567890"];//产生的对象是autorelease的。 [loopPool release]; } [pool release]; return (0); } // main |
以上示例来自:http://www.cocoachina.com/bbs/read.php?tid-15963-page-1.html,这篇文章也推荐初学者读一读。
Selector语法
Selector的概念可参考以下两篇博文:
http://ocen.javaeye.com/blog/518534
http://blogold.chinaunix.net/u3/105675/showart_2459210.html
简言之,Selector的作用是,可通过“方法名称”得到方法在类中的编号,然后用这个编号来调用方法(进行消息的发送)。
Selector支持延时发送消息,例如:
[self performSelector:@selector(showButton) withObject:nil afterDelay:1.5];
Selector只关心方法的原型,而不关心它所属的类。
文件 MyClass.h:
#import <Foundation/Foundation.h>
@interface Bird : NSObject { /* 超类: 鸟 */ } -(void) fly; -(void) fly: (NSNumber*) height; -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed; @end @interface Glede : Bird {} /* 子类:老鹰 */ -(void) fly; -(void) fly: (NSNumber*) height; -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed; @end |
文件 MyClass.m:
#import "MyClass.h"
@implementation Bird -(void) fly { NSLog(@"Bird.fly void"); } -(void) fly: (NSNumber*) height { NSLog(@"Bird.flyWithHeight %@", height); } -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed { NSLog(@"Bird.flyWithHeight %@, andSpeed %@", height, speed); } @end @implementation Glede -(void) fly { NSLog(@"Glede.fly void"); } -(void) fly: (NSNumber*) height { NSLog(@"Glede.flyWithHeight %@", height); } -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed { NSLog(@"Glede.flyWithHeight %@, andSpeed %@", height, speed); } @end |
文件 main.m:
#import <Foundation/Foundation.h>
#import "MyClass.h" int main( int argc, const char *argv[] ) { Glede* pGled = [Glede alloc]; Bird* pBird = [Bird alloc]; /* performSelector不支持基本类型,所以数值用NSNumber */ NSNumber *height = [[NSNumber alloc] initWithFloat:1000.0]; NSNumber *speed = [[NSNumber alloc] initWithFloat:10.0]; /* 通过方法名得到方法ID */ SEL fly = @selector(fly); //指向不带参数的fly SEL flyWithHeight = @selector(fly:); //指向带一个int参数的fly SEL flyWithHeightAndSpeed = @selector(fly:withSpeed:); //指向带二个int参数的fly /* 用pGled对象调用方法ID所对应的方法(或叫作发送消息给pGled) */ [pGled performSelector:fly]; [pGled performSelector:flyWithHeight withObject:height ]; [pGled performSelector:flyWithHeightAndSpeed withObject:height withObject:speed ]; /* 通过字符串得到方法ID */ SEL flyWithHeight2 = NSSelectorFromString(@"fly:"); SEL flyWithHeightAndSpeed2 = NSSelectorFromString(@"fly:withSpeed:"); /* 用pBird对象调用方法ID所对应的方法(或叫作发送消息给pBird) */ [pBird performSelector:flyWithHeight2 withObject:height ]; [pBird performSelector:flyWithHeightAndSpeed2 withObject:height withObject:speed ]; [pGled release]; [height release]; [speed release]; return 0; } |
属性--高级篇
属性的定义格式如下: 属性的定义格式如下:
@property (<parameters>) <type> <name>;
parameters经常用到的是 copy/retain/assign/noatomatic,它们都用来控制如何自动生成setter和getter,下面分别说明它们之间的区别:
假设要将以下变量设置成属性: NSString* name; 然后展开的setter函数可能是:
copy | retain | assign | |
setter函数的展开 | -(void) setName:(NSString*) newValue {
if (oldValue != newValue) {
[oldValue release];
oldValue = [newValue copy];
} } |
-(void) setName:(NSString*) newValue {
if (oldValue != newValue) {
[oldValue release];
oldValue = [newValue retain]; } } |
-(void) setName:(NSString*) newValue {
if (oldValue != newValue) {
oldValue = newValue; } } |
主要区别 | 会创建一个新对象 | 引用传入的对象,并将传入的对象引用计数加1 | 直接赋值,主要用于基本类型 |