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

接上一篇: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 直接赋值,主要用于基本类型
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值