• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
冲浪 Object-c
 

冲浪 Object-c

on

  • 1,744 views

 

Statistics

Views

Total Views
1,744
Views on SlideShare
1,744
Embed Views
0

Actions

Likes
5
Downloads
40
Comments
0

0 Embeds 0

No embeds

Accessibility

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

冲浪 Object-c 冲浪 Object-c Presentation Transcript

  • 深入浅出Object-C内存管理 演讲人:冲浪
  • 内存管理规则 只能释放或自动释放 所拥有的对象[MyObject alloc][MyObject retain];[MyObject copy];[MyObject autorelease];
  • 保留计数Objective-C使用了一 叫做持有计数(Retain Count)的机制来管理内存中的对象。 创建一个对象,该对象的保留计数为1。 向一个对象发送retain消息时,该对象的保留计数加1。 向一个对象发送release消息时,该对象的保留计数 1。 向一个对象发送autorelease消息时,该对象的保留计数会在 将来的某个阶段 1。
  • 例1:- (void)printHello { NSString *string = [[NSString alloc] initWithString:@"Hello"]; NSLog(string); [string release];}/ 用 alloc 创建对象 使 [string releaseCount] = 1 /
  • 例2:- (void)printHello { NSString *string; = [NSString stringWithFormat:@"Hello"]; NSLog(string);}/ 你拼不拥有 string ,所以你无需 release / Q:它们差 在 里?
  • 什么情况下用 autorelease 自动释放? 重点:autorelease并不是“自动释放”,而是“延后释放”,在一个运行周期 后被标记为autorelease会被释放掉。例1:– (NSArray *)sprockets { NSArray *array = [[NSArray alloc] initWithObjects:mainSprocket,auxiliarySprocket, nil]; return [array autorelease];}/ 正 / 使用 autorelease
  • 例2:– (NSArray *)sprockets { NSArray *array = [[NSArray alloc]initWithObjects:mainSprocket,auxiliarySprocket, nil]; return array;}/ 内存泄露 /
  • 例3:– (NSArray *)sprockets { NSArray *array = [[NSArray alloc]initWithObjects:mainSprocket,auxiliarySprocket, nil]; [array release]; return array;}/ 程序 / 常退出,因为 array 过早释放
  • 例4:– (NSArray *)sprockets { NSArray *array = [NSArrayarrayWithObjects:mainSprocket,auxiliarySprocket, nil]; return array;}/ 你并不拥有 arrayWithObjects ,所以你不需要释放 /
  • 自动释放池1.置于一个堆栈中,通常被称为被“嵌套”的。2.新的自动释放池,它被添加到堆栈的顶部。3. 对象收到autorelease,它被添加到当前线程栈顶的自动释放池中。4.当被回收时,从堆栈中被删除。5.Application Kit会在一个事件周期的 端—比如鼠标按下事件—自动创建一个自动释放池,并且在事件周期的结尾释放它.
  • 共享对象的有效性例1:heisenObject = [array objectAtIndex:n];[array removeObjectAtIndex:n];/ heisenObject 无效 /
  • 例2:id parent = <#create a parentobject#>;/ ... /heisenObject = [parent child] ;[parent release];/ heisenObject 无效 /
  • 例3:heisenObject = [[array objectAtIndex:n]retain];[array removeObjectAtIndex:n];/ use heisenObject. /[heisenObject release];/ 正常运行 /
  • 集合例1NSMutableArray *array;NSUInteger i;for (i = 0; i < 10; i++) { NSNumber *convenienceNumber = [NSNumber numberWithInteger:i]; [array addObject:convenienceNumber];}//在这段代码中, 没有调用alloc,因此也没有必要调用release。没有必要保留新的数字对象(convenienceNumber),因为数组会为 代劳。
  • 例2NSMutableArray *array;NSUInteger i;for (i = 0; i < 10; i++) { NSNumber *allocedNumber = [[NSNumber alloc] initWithInteger: i]; [array addObject:allocedNumber]; [allocedNumber release];}/ 由于数组在用addObject:方法添加数字时对其进行了保留 + 1,因此只要 /它还在数组中就不会被释放。
  • 从方法返回的对象例1- (NSString *)fullName { NSString *string = [NSString stringWithFormat:@"%@ %@", firstName,lastName]; return string;}// 并不拥有stringWithFormat返回的字符串,所以它可以安全地从该方法中返回
  • 例2- (NSString *)fullName { NSString *string = [[[NSString alloc] initWithFormat:@"%@%@", firstName, lastName] autorelease]; return string;}// 拥有alloc返回的字符串,但 随后向它发送了一条autorelease消息,因此在 失去它的引用之前, 已经放弃了所有权
  • 例3:- (NSString *)fullName { NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",firstName, lastName] release]; return string;}/ 错误 /
  • 例4:- (NSString *)fullName { NSString *string = [[NSString alloc] initWithFormat:@"%@ %@",firstName, lastName]; return string;}/ 内存泄露 /
  • 存取方法MyClass.h:@interface MyClass : NSObject { MyObject *myObject;}@property (nonatomic, retain) MyObject *myObject;@end
  • MyClass.m:@synthesize myObject;-(id)init{ if(self = [super init]){ MyObject * aMyObject = [[MyObject alloc] init]; self.myObject = aMyObject; [aMyObject release]; } return self;} Q: 为什么要这么 杂的赋值? 为什么要加self. ? 直接写成self.myObject = [[MyObject alloc] init];不是也没有错么? 不加self有时好像也是正常的?
  • 看以下例子retainCount变化:间接赋值: 1.加self.: MyObject * aMyObject = [[MyObject alloc] init]; //aMyObjectretainCount = 1; self.myObject = aMyObject; //myObject retainCount = 2; [aMyObject release];//myObject retainCount = 1; 2. 不加self.: MyObject * aMyObject = [[MyObject alloc] init]; //aMyObjectretainCount = 1; myObject = aMyObject; //myObject retainCount = 1; [aMyObject release];//对象己经被释放
  • 直接赋值: 3.加self.: self.myObject = [[MyObject alloc] init]; //myObject retainCount = 2; 4. 不加self.: myObject = [[MyObject alloc] init]; //myObject retainCount = 1;
  • MyClass.h@interface MyClass : NSObject { MyObject * _myObject;}@property (nonatomic, retain) MyObject *myObject;@endMyClass.m@synthesize myObject = _myObject; 如果你用 self._myObject = aMyObject; 或者 myObject = aMyObject; 你会得到一个错误. 为什么 ? self.myObject = [[MyObject alloc] init]; 为什么会有内存泄露?
  • 实现方法get方法是:-(MyObject*)myObject{ return _myObject;} Set方法是: / assign / -(void)setMyObject:(id)newValue{ _myObject = newValue; }
  • / retain /-(void)setMyObject:(id)newValue{ if (_myObject != newValue) { [_myObject release]; _myObject = [newValue retain]; }} / copy / -(void)setMyObject:(id)newValue{ if (_myObject != newValue) { [_myObject release]; _myObject = [newValue copy]; } }
  • 例子NSString* s = [[NSString alloc]initWithString:@”This is a test string”];s = [s substringFromIndex:[s rangeOfString:@"a"].location];//内存泄露[s release];//错误释放
  • 谢谢