Objective-C二传手内存管理

Ari*_*riX 2 iphone setter memory-management objective-c

关于Objective-C内存管理仍然有点困惑.我认为我的困惑源于自动释放的含义.

NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];
Run Code Online (Sandbox Code Playgroud)

现在,我应该如何处理视图控制器的setAccountDictionary方法中的accountDictionary?现在我只是将实例变量"accountDictionary"设置为返回的内容.我应该将其设置为保留的,然后释放返回的那个吗?考虑到NSS​​tring的propertyList方法是自动释放的,我的setter代码块应该是什么样的?

顺便说一句,如果我发布theBackendResponse,我会丢失accountDictionary吗?我假设不...

Bar*_*ark 14

调用[objectInstance autorelease]会向当前添加一个对象NSAutoreleasePool.当该池收到drain消息时,它会向release池中的所有对象发送一个消息.如果这些对象的retainCount中的任何一个达到0,那么它们将在该点被释放.自动释放的目的是允许您在"将来的某个时间"标记要释放的对象.这对于返回新分配的对象但希望释放它的方法特别有用,这样调用者就不必获取返回对象的所有权.方法可能如下所示:

- (id)myMethod {
    id myObj = [[SomeClass alloc] init];

    ...

    return [myObj autorelease];
}
Run Code Online (Sandbox Code Playgroud)

如果调用者想要获取返回值的所有权,myMethod则调用者将retain返回值,否则忽略它.当电流NSAutoreleasePool耗尽时,myObj将获得释放消息.如果没有其他对象拥有它(即已向其发送retain消息),它将被取消分配.

所有这些都在"可可内存管理编程指南"中进行了解释.即使你已经阅读过它,也总是值得一读.

那么,回答你的问题:

首先,你应该释放theBackendResponse.如果不这样做,你会泄漏内存.您不需要知道accountDictionary字符串的作用:如果需要保留引用,它将保留theBackendResponse.您拥有所有权,theBackendResponse因为您alloc必须放弃所有权(通过release或间接通过autorelease).

其次,setAccountDictionary:如果要分别保留对该对象或值的引用,则必须保留或复制参数.标准的setter方法看起来像这样(假设你不需要原子语义):

-(void)setAccountDictionary:(NSDictionary*)newDict {
  if(newDict != accountDictionary) {
    id tmp = accountDictionary;
    accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back.
    [tmp release];
  }
}
Run Code Online (Sandbox Code Playgroud)

您还必须记住releasedealloc方法中的accountDictionary:

- (void)dealloc {
    [accountDictionary release];
    [super dealloc];
}
Run Code Online (Sandbox Code Playgroud)

既然你似乎是使用NSViewController,我认为你是在Leopard(OS X 10.5),在这种情况下,你或许应该使用@property@synthesized的getter/setter如果可能的话.为此,请添加

@property (copy,readwrite) NSDictionary * accountDictionary; 
Run Code Online (Sandbox Code Playgroud)

向全班宣言@interface.并@synthesize accountDictionary;@implementation块中为您的控制器类添加一个指令.