现在的位置: 首页 > 综合 > 正文

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

2014年02月01日 ⁄ 综合 ⁄ 共 4410字 ⁄ 字号 评论关闭

接上一篇: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

直接赋值,主要用于基本类型

抱歉!评论已关闭.