!!!Obj-c on Mac --- Chapter 9 Memory Management
来源:互联网 发布:网络发彩信 编辑:程序博客网 时间:2024/06/06 18:41
Object Life Cycle
Reference Counting
Every object has an integer associated with it, known as its reference count orretain count.
When an object is created via alloc or new, or via a copy message (which makes a copy of the receiving object), the object’s retain count is set to 1. To increase its retain count, send the object a retain message. To decrease its retain count, send the object a release message.
When an object is about to be destroyed because its retain count has reached 0, Objective- C will automatically send the object a dealloc message. You can override dealloc in your objects. Do this to release any related resources you might have allocated. Don’t ever call dealloc directly.
To find out the current retain count, send the retainCount message.
- (id) retain;- (void) release;- (unsigned) retainCount;Retain returns an id. That way, you can chain a retain call with other message sends, incrementing its retain count and then asking it to do some work. For instance, [[car retain]
setTire: tire atIndex: 2]; asks car to bump up its retain count and perform the setTire action.
Object Ownership
An object with instance variables that point to other objects is said to own those other objects. Similarly, a function that creates an object is said to own that object.
Retaining and Releasing in Accessors
Bad code 1:
- (void) setEngine: (Engine *) newEngine{ engine = [newEngine retain]; // BAD CODE: do not steal. See fixed version below.} // setEngineProblem:
Engine *engine1 = [Engine new]; // count: 1[car setEngine: engine1]; // count: 2[engine1 release]; // count: 1Engine *engine2 = [Engine new]; // count: 1[car setEngine: engine2]; // count: 2
Bad code 2:
- (void) setEngine: (Engine *) newEngine{ [engine release]; engine = [newEngine retain]; // More BAD CODE: do not steal. Fixed version below.} // setEngineProblem:
Engine *engine = [Engine new]; // count: 1Car *car1 = [Car new];Car *car2 = [Car new];[car1 setEngine: engine]; // count: 2[engine release]; // count 1[car2 setEngine: [car1 engine]]; // oops!Good code:
- (void) setEngine: (Engine *) newEngine{[newEngine retain];[engine release];engine = newEngine;} // setEngine
Autorelease
Cocoa has the concept of the autorelease pool. It’s a pool (collection) of stuff, presumably objects, that automatically get released.
NSObject provides a method called autorelease:
- (id) autorelease;This method schedules a release message to be sent at some time in the future. The return value is the object that receives the message; retain uses this same technique, which
makes chaining calls together easy. What actually happens when you send autorelease to an object is that the object is added to an NSAutoreleasePool. When that pool is destroyed, all the objects in the pool are sent a release message.
- (NSString *) description{NSString *description;description = [[NSString alloc]initWithFormat: @"I am %d years old", 4];return ([description autorelease]);} // descriptionIn the Foundation tools we’ve been using, the creation and destruction of the pool has been explicit:
NSAutoreleasePool *pool;pool = [[NSAutoreleasePool alloc] init];...[pool release];When you create an autorelease pool, it automatically becomes the active pool. When you release that pool, its retain count goes to 0, so it then gets deallocated. During the deallocation, it releases all the objects it has.
You may have seen in Xcode’s autogenerated code an alternate way of destroying an autorelease pool’s objects: the -drain method. This method empties out the pool without destroying it. -drain is only available in Mac OS X 10.4 (Tiger) and later. In our own code (not generated by Xcode), we’ll be using -release, since that will work on versions of the OS back to the beginning of time.
The Rules of Cocoa Memory Management
■ When you create an object using new, alloc, or copy (for example,alloc
,newObject
, or mutableCopy
), the object has a retain count of 1. You are responsible for sending the object a release or autorelease message when you’re done with it. That way, it gets cleaned up when its useful life is over.
■ When you get hold of an object via any other mechanism, assume it has a retain count of 1 and that it has already been autoreleased. You don’t need to do any further work to make sure it gets cleaned up. If you’re going to hang on to the object for any length of time, retain it and make sure to release it when you’re done.
■ If you retain an object, you need to (eventually) release or autorelease it. Balance these retains and releases.
If you get the object from new, alloc, or copy, you need to arrange its demise, usually with a release:
NSMutableArray *array;array = [[NSMutableArray alloc] init]; // count: 1// use the array[array release]; // count: 0If you get the object from any other mechanism, such as arrayWithCapacity:, you don’t have to worry about destroying it:
NSMutableArray *array;array = [NSMutabelArray arrayWithCapacity: 17];// count: 1, autoreleased// use the arrayarrayWithCapacity: is not alloc, new, or copy, so you can assume that the object being returned has a retain count of 1 and has already been autoreleased. When the autorelease pool goes away, array is sent the release message, its retain count goes to 0, and its memory is recycled.
NSColor *color;color = [NSColor blueColor];// use the colorblueColor is not alloc, new, or copy, so you can assume it has a retain count of 1 and is autoreleased. blueColor returns a global singleton object—a single object that’s shared by every program that needs it—and won’t actually ever get destroyed.
Hanging on to Objects
If you’re getting an object from init, new, or copy, you don’t need to do anything special. The object’s retain count will be 1, so it will stick around. Just be sure to release the object in the dealloc method of the owner- object that’s hanging on to it:
- (void) doStuff{// flonkArray is an instance variableflonkArray = [NSMutableArray new]; // count: 1} // doStuff- (void) dealloc{[flonkArray release]; // count: 0[super dealloc];} // deallocIf you get an object from something other than init, new, or copy, you need to remember to retain it.
event loop
A typical graphical application spends a lot of time waiting on the user to do something. The program sits twiddling its thumbs until the very slow human at the controls decides to click the mouse or press a key. When one of these events does happen, the program wakes up and gets to work doing whatever is necessary to respond to the event. After the event is handled, the application goes back to sleep waiting for the next event.
To keep your program’s memory footprint low, Cocoa creates an autorelease pool before it starts handling the event and destroys the pool after the event is handled. This keeps the amount of accumulated temporary objects to a minimum.
- (void) doStuff{ // flonkArray is an instance variable flonkArray = [NSMutableArray arrayWithCapacity: 17]; // count: 1, autoreleased [flonkArray retain]; // count: 2, 1 autorelease} // doStuff- (void) dealloc{ [flonkArray release]; // count: 0 [super dealloc];} // dealloc
KEEPING THE POOL CLEAN
The autorelease pool is purged at well- defined times: when it’s explicitly destroyed in your own code or at the end of the event loop when using the AppKit. You don’t have to worry about a demon that goes around destroying autorelease pools at random. You also don’t have to retain each and every object you use, because the pool won’t go away in the middle of a function.
Sometimes autorelease pools don’t get cleaned out as often as you would like.
int i;for (i = 0; i < 1000000; i++) {id object = [someArray objectAtIndex: i];NSString *desc = [object description];// and do something with the description}The way to work around this is to create your own autorelease pool inside the loop.
NSAutoreleasePool *pool;pool = [[NSAutoreleasePool alloc] init];int i;for (i = 0; i < 1000000; i++) {id object = [someArray objectAtIndex: i];NSString *desc = [object descrption];// and do something with the descriptionif (i % 1000 == 0) {[pool release];pool = [[NSAutoreleasePool alloc] init];}}[pool release]
Garbage Collector
Objective-C 2.0 introduces automatic memory management, also called garbage collection.
The Objective- C garbage collector is a generational garbage collector. Newly created objects are much more likely to turn into garbage than objects that have been hanging around for awhile. At regular times, the garbage collector starts looking at your variables and objects and follows the pointers between them. Any object it discovers without anything pointing to it is garbage, which is fit to be thrown away. The worst thing you can do is keep a pointer to an object that you’re done with. So if you point to an object in an instance variable (recall composition), be sure to assign nil to your instance variable, which removes your reference to this object and lets the garbage collector know it can be purged. Like the autorelease pool, garbage collection is triggered at the end of an event loop. You can also trigger garbage collection yourself if you’re not in a GUI program
- !!!Obj-c on Mac --- Chapter 9 Memory Management
- !!!Obj-c on Mac --- Chapter 2 ~ 4
- !!!Obj-c on Mac --- Chapter 5 ~ 7
- !!!Obj-c on Mac --- Chapter 13 Protocols
- !!!Obj-c on Mac --- Chapter 17 NSPredicate
- Chapter 9 Memory Management
- !!!Obj-c on Mac --- Chapter 8 Foundation Kit
- !!!Obj-c on Mac --- Chapter 10 - 12 Initialization Property Category
- !!!Obj-c on Mac --- Chapter 15 File Loading and Saving
- !!!Obj-c on Mac --- Chapter 16 Key-Value Coding
- Chapter 4. Memory Management Debugging
- Pointers On C Chapter 9
- c memory management(zz)
- C++ Memory Management
- MMU(Memory Management Units) Chapter-14
- Memory management in C programs
- Memory management in C programs
- Memory management in C programs
- Hibernate主键生成策略的验证之Increment
- 递归字符串查找
- codeforces #221(div2)B. I.O.U.
- sicily 1200stick
- Spring - Bean生命周期
- !!!Obj-c on Mac --- Chapter 9 Memory Management
- Spring - Bean作用域
- 如何利用Python和win32编程避免重复性体力劳动(二)——菜单操作:GetMenu,GetSubMenu,GetMenuItemID以及wParam的HIWORD&LOWORD
- 黑马程序员---Java基础学习之算术运算符、赋值运算符、比较运算符、逻辑运算符
- 一张白纸,从头开始
- 26-java中int转string的三种方法
- 数组里面都是人的名字,分割成:例如:老杨|老苏|老邹…”(老杨,老苏,老邹,老虎,老牛,老蒋,老王,老马)
- 黑马程序员---Java基础学习之判断结构(if)
- 百度地图切割算法讲解