Practically speaking, this means that you don't have to worry about memory management in Cocoa applications the way you used to, if you can require Leopard. You're not entirely freed from worrying about memory management, of course: For one thing, you need to be careful about multithreading, as any
-finalize methods you implement will be run in a collector thread. For another, you can still easily over-root objects that should be collectable; this is a common cause of memory leaks in garbage-collected applications, and should be familiar to Java developers.To address the over-rooting problem, zeroing weak references have been introduced to Objective-C. By prefixing an instance variable declaration with
__weak, you tell the garbage collector that if it's the only reference to an object that the object should be considered collectable. And when the object is collected, the instance variable will be set to nil for you!This works for any number of weak references to a particular collectable object. So long as there are no strong references to an object — which are the regular kind of non-weak references you're used to — an object is eligible for collection no matter how many weak references there are to it. Thus I can create an object, assign it to a thousand different
__weak instance variables, and then not assign it to any regular instance variables, and it will eventually be collected and all of those __weak instance variables will be "simultaneously" changed to nil.Because objects are commonly stored in collections — for example, in static
NSMutableDictionary instances that are used as caches — the Foundation framework also has some additional classes that can support weak references. There's NSPointerArray, NSHashTable, and NSHashMap: - NSPointerArray is a lot like NSMutableArray, but it can contain arbitrary pointers (not just objects) and also supports
nilelements and can hold zeroing weak references. - NSHashTable is a lot like NSMutableSet, but it can hold zeroing weak references.
- NSHashMap is a lot like NSMutableDictionary, but it can hold zeroing weak references for either its keys or its values, and doesn't have to copy its keys.
One other thing you can do is create hybrid applications and frameworks. As Scott Stevenson shows in his Objective-C 2.0 tutorial, you can build an application or framework such that garbage collection is either supported or required. For frameworks this is particularly useful; after all, you may want to use a framework in both a GC and in a non-GC application. By building it as GC-supported rather than GC-required, you can create a single framework binary that can be used in either.
How does this work? It's simple: When running under GC, the Objective-C runtime will "eat" all
-retain, -release and -autorelease messages such that objects never receive them, and objects will never be sent a -dealloc. However, you can still write your code such that it has all of the proper non-GC memory management too. Then when you build it GC-supported, if it's loaded into a process that is using the collector it will use GC, but if it's loaded into a process using reference counting it will behave correctly there too.There are a couple of things that you can't do with GC. One is that you can't use a non-GC framework in a GC application; an entire process has to be either GC or non-GC. Thus if you use third-party frameworks that haven't been made hybrid, GC-supporting frameworks, you'll need to stick with reference counting until the frameworks are updated.
The other thing you can't do with GC is write code that makes use of GC but that runs on pre-Leopard operating systems. Code built for GC uses certain runtime calls that are not present in earlier versions of the Objective-C runtime, and unfortunately this means that code built for GC requires the Leopard version of the runtime to execute. Leopard contains so many other compelling developer and end-user features, and other Objective-C 2.0 features also require Leopard, so in practice this probably won't be such a huge deterrent.
Update: At jcr's request, I've expanded the discussion of weak references to make it clear that the number of weak references to an object doesn't matter; as long as there are no strong references to it (whether in instance variables, reachable via globals, or on the stack or in registers), it will be eligible for collection.
![[info]](http://l-stat.livejournal.com/img/userinfo.gif)
![[info]](http://l-stat.livejournal.com/img/openid-profile.gif)
over-root?
(Anonymous)
2007-10-29 03:01 am (UTC)