Objective-C 学习笔记(22): 内存管理、Selector和属性

    技术2022-05-18  13

    接上一篇: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 直接赋值,主要用于基本类型

    最新回复(0)