在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Objective-C Memory Management 内存管理 2 2.1 The Rules of Cocoa Memory Management 内存管理规则 (1)When you create an object using new, alloc, or copy, the object has a 当你通过new,alloc,copy获得一个对象时,retain count是1 。你需要负责该对象的释放或被自动释放。 (2)When you get hold of an object via any other mechanism, assume it has 当你通过其他方式获得一个对象时,假设该对象 retain count 是1,并且已经自动释放,那么你不需要做别的工作。 当你需要保持这个对象任意长时间的时候,你应该retain 它,当你不用的时候要确保释放它。 (3)If you retain an object, you need to (eventually) release or autorelease it. Balance these retains and releases. 当你retain 一个对象时,你最终需要release或autorelease 它。
Whenever you get hold of an object, you must be aware of two things: how you got it and how long you plan on hanging on to it 当你获得一个对象时,你必须明白你怎么获得的和你打算用它多长时间。
2.2 Transient Object Let's take a look at some common memory-management life cycle scenarios. 让我们看一些内存管理的场景。 (1)如果你只是短暂的拥有对象,通过alloc ,copy ,new 你应该安排释放。 NSMutableArray *array; array = [[NSMutableArray alloc] init]; // count: 1 // use the array [array release]; // count: 0 (2)如果对象通过其他机制,则你不需要担心释放的问题。 NSMutableArray *array; array = [NSMutableArray arrayWithCapacity: 17]; // count: 1, autoreleased // use the array
arrayWithCapacity: 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. arraywithcapacity 不是通过alloc ,new ,or copy 获得的,所以你能假设该对象被返回一个retain count 为1,并且被自动释放了。当自动释放池释放了,那就会发送一个消息让你释放。
NSColor *color; color = [NSColor blueColor]; // use the color blueColor不是通过alloc,new,copy获得的,所以你应该假设retain count 为1,并且自动释放。 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, but you don't need to worry about those implementation details. All you need to know is that you do not need to explicitly release color. 当然blueColor 返回一个全局单例对象,一个对象被整个程序使用的。所以它不需要被释放,但是你不需要了解这些细节,只要明白你不需要明确地释放就行了。 2.3 Hanging on to Objects Frequently, you'll want to keep an object around for more than a couple of lines of code. 你经常需要保持一个对象不仅仅一些行。
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: 当你是通过init,new,copy得到的,那么你不需要做特别的事情。 只需要在delloc 方法中,释放就行了。 - (void) doStuff { // flonkArray is an instance variable flonkArray = [NSMutableArray new]; // count: 1 } // doStuff - (void) dealloc { [flonkArray release]; // count: 0 [super dealloc]; } // dealloc
If you get an object from something other than init, new, or copy, you need to remember to retain it. 当一个对象不是来自new,init,or copy ,你应该记住retain 它。 When you're writing a GUI application, think in event loops. You want to retain autoreleased objects that will survive for longer than the current event loop. 当在一个GUI application,想event loops。你想retain autoreleased 对象,比当前的events loops 生存时间更长。 - (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 If we didn't have retain in doStuff, flonkArray would get destroyed unexpectedly. 如果我们不retain doStuff,那么flonkArray可能destroyed 不可预期。 Remember that 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. autorelease pool清空在预定好的时间:当明确指明时和在event loop 结束时。 2.4 Automatic memory management, also called garbage collection 自动内存管理 垃圾回收机制 像java 和python 也有垃圾回收。 只有mac应用可以用垃圾回收 但是垃圾回收机制是可选的。 Just go to the Build Settings of the project information window, and choose Required [-fobjc-gc-only] 去 Build Settings 选择[-fobjc-gc-only]. 这个好像在xcode5 已经不存在了。并且ios一直没有垃圾回收机制。 就当了解了。 2.5 Auotmatic Reference Counting 自动引用计数 What's the deal with no garbage collection in iOS? The main argument against garbage collection in iOS is that you don't know exactly when the garbage collector is going to show up. iOS没有用垃圾回收机制,一个重要原因是用garbage collector时,你不确定什么时候出现垃圾回收。 Users don't want to have a game or phone call pause while the system cleans up memory. 用户不想再玩游戏或打电话的时候系统清理内存。 苹果想出了一个办法:atuomatic reference counting (ARC). As the name suggests, ARC keeps track of your objects and decides which ones you meant to keep and which ones you didn't. It's a little like having a butler or personal assistant in your memory management. ARC 跟踪你的对象,决定那个要保持,那个要取消。就像一个你的内存的私人助理。 When you use ARC, you allocate and use objects as you would normally, and the compiler inserts the retains and releases for you – you don't put them in yourself. 当你用arc时,你只需要用对象即可。编译器将添加或删除retain 和release信息。 ARC is not a garbage collector. As we've already discussed, garbage collection does its work at runtime, via code that runs and checks your objects periodically. In contrast, ARC does its thing at compile time. ARC 不是垃圾回收机制。垃圾回收机制发生在运行时,而arc 发生在编译时。 It inserts the proper retains and releases, so memory management happens as it would in well-written manually managed code. 编译时插入适当的retain 和release,因此,内存管理因为很好地自动填充代码。 ARC is an opt-in feature, which means you must explicitly enable or disable it. ARC 是个opt-in的特色,可供选择的特性。 ARC only works with retainable object pointers (ROPs). There are three kinds of retainable object pointers: 当然,arc 只能识别retainable object pointers 。 . 1) Block pointers . 2) Objective-C object pointers . 3) Typedefs marked with __attribute__((NSObject)) All other pointer types, such as char * and CF objects such as CFStringRef, are not ARC compatible. 所有其他的指针像char * 和CFStringRef 不能和arc。 If you want to use ARC in your code, you must meet three requirements: 如果想用arc需要满足一下: 你必须明确地知道那个对象需要被管理。 (2)You must be able to indicate how to manage an object. 你需要指示怎样管理一个对象。 你需要明确地传递对一个对象的拥有关系。 The first requirement means that a root-level object of collections of objects must know how to manage its child objects. 第一个要求是说你必须知道一个容器的根对象如何管理它的子对象。 For example, let's say you have an array of strings created with malloc: NSString **myString; myString = malloc(10 * sizeof(NSString *)); This code creates a C array that points to ten strings. Because C arrays are not retainable, you can't use ARC on this structure. 这个代码创建了一个c array指向10个strings,但是c arrays不能被retainable。所以不能用arc。 第二要要求:This requirement usually means you must be able to increment and decrement the retain count on an object, which pretty much means anything that is derived from NSObject is cool. 你必须能增加或减少retain count。也就是说源于NSObject 的事情是很好的。 The third requirement states that when passing around an object, your program needs to be able to pass ownership of the object between the caller and the callee 第三个要求是当传送对象时,你的程序需要能够传递一个对象的拥有关系在调用和被调用间。
2.6 Sometimes weak is good 弱引用 If you manage the memory of an object, you're said to have a strong reference to the object. If you are not managing its memory, you have (you guessed it) a weak reference. 当你管理一个对象的内存时,你有一个强的引用。如果你不管理,你就有一个弱的引用。 you have an object A that was created by some other object and has a retain count Object A creates an object B as its child, and object B has a retain count of 1
In this example, object A has a strong reference to Object B, because object A created object B. Now, if object B gets a strong reference to object A, the retain count on Object A increases to 2 这个时候,如果对象b有一个强 的引用对对象A,那么对象A 的retain count 增加了2 。 Eventually, the owner of object A no longer needs it. The owner calls release on Object A, which decrements its retain count to 1. 最终拥有者不想再拥有A了,那么就应该释放A,那么A的retain count 成为了1. But object B, which was created by object A, owns that 1 retain count. Because both objects have nonzero retain counts, neither of them is released. This is a classic memory leak: the program has no access to the objects, but they're still using memory 这个时候没有对象引用A,因为这两个对象都不是retain count 为0 ,所以这边是典型的memory leak 内存泄露:程序没有存储到对象,但是他们仍然在内存中。
为了解决这个问题,我们通过分配得到B对对象A的引用。使用weak reference ,retain count 不增加了。 So when object A's owner releases it, its retain count goes to zero, it releases B, and both A and B relinquish their precious memory
这很好,但是还不够,假如有三个对象,你不再用A了,并且有个强引用到B,并且C有一个弱引用到C, 如果A释放了B,C仍然有个weak reference ,但是不在valid。再使用可能引起崩溃。
Here's the solution: objects that automagically clean up their weak references. These special weak references are called zeroing weak references, because when the object they point to is released, they are set to zero (nil) and can be handled like any other nil pointer 解决办法是:对象自动清理weak references。这些特殊的weak reference称为 zeroing weak references,因为当他们指向的对象为被释放的时候,那么他们也就指向了zero(nil)了。
To use zeroing weak references, you have to explicitly declare them. 你必须明确指明你要使用zero weak reference 。 There are two ways to declare zeroing weak references: by using the __weak keyword when declaring a variable, or by using the weak attribute on properties: __weak NSString *myString; @property(weak) NSString *myString; Apple provides the __unsafe_unretained keyword and unsafe_unretained attribute, both of which tell ARC that the specified reference is weak. apple 还提供了__unsafe_unretained关键字和unsafe_unretained属性当指明arc 指定的reference是弱引用。 there is also a __strong keyword and strong attribute. __strong和strong attribute 是强引用。
记住关键字和属性(key 和attribute是互斥的)
2.7 A new convertible 将原有项目转成ARC Xcode provides a handy procedure to convert our existing projects to ARC. autorelease
|
请发表评论