目标C-ARC-何时使用@autoreleasepool [英] Objective C - ARC - When to use @autoreleasepool
问题描述
我正在阅读有关ARC的一些文章,我看到了:
I was reading a little about ARC and I saw this:
@interface Address : NSObject {
@public
NSString *city;
}
@end
@implementation Address
- (Address*) init: (NSString*) c {
city = c;
return self;
}
- (void) dealloc {
NSLog(@"Destroying address: %@", city);
}
@end
@interface Customer : NSObject {
NSString *name;
Address *addr;
}
@end
@implementation Customer
- (Customer*) init: (NSString*) n withAddress: (Address*) a {
//Note 1: Automatic retain on assignment
name = n;
addr = a;
return self;
}
- (void) dealloc {
NSLog(@"Destroying: %@", name);
//Note 2: Automatic release of member variables
}
@end
Customer* objectReturnTest() {
NSString * n = [[NSString alloc] initWithString: @"Billy Bob"];
Address * a = [[Address alloc] init: @"New York City"];
Customer *c = [[Customer alloc] init: n withAddress: a];
//Note 3: ARC will put the returned object in autorelease pool.
return c;
}
A couple of basic things to note here. As "Note 1" says, when an object is assigned to a variable, a call to retain is made automatically. This increments the reference count. As "Note 2" says, when an object is destroyed, all member variable objects are released for you. You no longer have to do that from the dealloc method.
Finally, when a method returns a newly created object, ARC will put the returned object in an autorelease pool. This is stated in "Note 3".
Now, let’s use the code.
int main (int argc, const char * argv[])
{
NSString * n = [[NSString alloc] initWithString: @"Johnny Walker"];
Address * a = [[Address alloc] init: @"Miami"];
Customer *c = [[Customer alloc] init: n withAddress: a];
NSLog(@"Before force release");
c = nil; //Force a release
NSLog(@"After force release");
@autoreleasepool {
Customer *c2 = objectReturnTest();
}
NSLog(@"After autorelease pool block.");
return 0;
}
The log output from this code will be:
Before force release
Destroying: Johnny Walker
After force release
Destroying: Billy Bob
Destroying address: New York City
After autorelease pool block.
Destroying address: Miami
A couple of things to note here. See how force release works. We set a variable to nil. ARC immediately releases the reference count. This causes the Customer object "Johnny Walker" to get destroyed. But, the member Address object "Miami" doesn’t get destroyed. This object gets destroyed at the very end of the main method. This is an extremely odd and non-intuitive behavior. Technically, this is not a memory leak, but, in reality member variables can pile up and take up a lot of memory. This is just as bad as memory leak.
The object return test works as expected. Customer "Billy Bob" is put in auto release pool. At the end of the @autoreleasepool block, the pool is drained and the object is released.
看这部分;
int main (int argc, const char * argv[])
{
NSString * n = [[NSString alloc] initWithString: @"Johnny Walker"];
Address * a = [[Address alloc] init: @"Miami"];
Customer *c = [[Customer alloc] init: n withAddress: a];
NSLog(@"Before force release");
c = nil; //Force a release
NSLog(@"After force release");
@autoreleasepool {
Customer *c2 = objectReturnTest();
}
NSLog(@"After autorelease pool block.");
return 0;
}
当他这样做时c = nil; 不应该全部销毁a和n吗?但是它说输出只是n被破坏了. 有人可以解释为什么吗?
When he does c = nil; shouldn't c a and n all be destroyed? Yet it says the output is only that n is destroyed.. Can someone explain why?
他说结果和内存泄漏一样糟糕,那么如何解决呢?
And he says the outcome is as bad as a memory leak, then how do you fix it?
最后一个问题,何时应该使用@autoreleaasepool?
And one last question, when should you use @autoreleaasepool?
推荐答案
c = nil; //Forces a release
一个Customer
实例被释放,因为没有人保留它,因此输出是
a Customer
instance is deallocated because no one is retaining it, so as a result the output is
毁灭:约翰尼·沃克
Destroying: Johnny Walker
但n
和a
尚未取消分配,因为它们仍保留在作用域中,并且尚未将nil
分配给它们.
but n
and a
have not been deallocated because they still remain in the scope and nil
has not been assigned to them.
我不认为这是任何形式的内存泄漏
and I don't think this is any kind of memory leak
除非您正在执行类似的操作,否则通常不需要使用@autorelasepool
you normally do not need to use @autorelasepool unless you are doing something like this
- (void)myMethod {
for (int i = 0; i < 1000000; i++) {
NSString *string = [NSString stringWithFormat:@"%d", i];
// do something with string
}
}
在循环期间将分配超过1000000个NSString.在方法返回之后(实际上是在此运行循环之后)将释放它们,但它们已经消耗了过多的内存.因此应替换为
Than 1000000 NSString will be allocated during loop. They will be deallocated after the method returned (actually after this runloop) but already consume too much memory. Therefore should replace to
- (void)myMethod {
for (int i = 0; i < 1000000; i++) {
@autoreleasepool {
NSString *string = [NSString stringWithFormat:@"%d", i];
// do something with string
}
}
}
you should read this to learn more about memory management https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-CJBFBEDI
这篇关于目标C-ARC-何时使用@autoreleasepool的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!