iPhone - 自定义对象内的 NSMutableArray。什么时候发布?
我应该什么时候释放[self.activeLocations]
,它是我的自定义对象中的一个NSMutableArray
?我还在 initWithValue
中遇到内存泄漏。
还有下面的 Location
对象。我是否正确调用并释放了它?
Custom Object.m 中的方法:
- (id)initWithValue:(NSString *)value {
if ((self = [super init])) {
self.couponId = [value valueForKey:@"couponId"];
self.couponName = [value valueForKeyPath:@"couponName"];
self.qrCode = [value valueForKeyPath:@"description"];
self.companyName = [value valueForKeyPath:@"companyName"];
self.categoryName = [value valueForKeyPath:@"categoryName"];
self.distance = [value valueForKeyPath:@"distance"];
NSDictionary *activeLocationsDict = [value valueForKeyPath:@"activeLocations"];
//self.activeLocations = [[[NSMutableArray alloc] init] autorelease];
self.activeLocations = [NSMutableArray array];
for (id val in activeLocationsDict) {
// Add JSON objects to array.
Location *l = [[Location alloc] initWithValue:val];
[self.activeLocations addObject:l];
[l release];
}
}
return self;
}
- (void)dealloc {
[super dealloc];
couponId = nil;
couponName = nil;
qrCode = nil;
companyName = nil;
categoryName = nil;
distance = nil;
activeLocations = nil;
}
我的 Custom Object.h
@interface Coupon : NSObject {
NSNumber *couponId;
NSString *couponName;
NSString *qrCode;
NSString *companyName;
NSString *categoryName;
NSString *distance;
NSMutableArray *activeLocations;
}
@property (nonatomic, copy) NSNumber *couponId;
@property (nonatomic, copy) NSString *couponName;
@property (nonatomic, copy) NSString *qrCode;
@property (nonatomic, copy) NSString *companyName;
@property (nonatomic, copy) NSString *categoryName;
@property (nonatomic, copy) NSString *distance;
@property (nonatomic, retain) NSMutableArray *activeLocations;
- (id)initWithValue:(NSString *)value;
这就是我使用上述 initWithValue
的方式:
- (NSMutableArray *)createArrayOfCoupons:(NSString *)value {
NSDictionary *responseJSON = [value JSONValue];
// Loop through key value pairs in JSON response.
//NSMutableArray *couponsArray = [[NSMutableArray alloc] init] autorelease];
NSMutableArray *couponsArray = [NSMutableArray array];
for (id val in responseJSON) {
// Add JSON objects to array.
Coupon *c = [[Coupon alloc] initWithValue:val];
[couponsArray addObject:c];
[c release];
}
return couponsArray;
}
我在上述方法中的 initWithValue
上也遇到了内存泄漏。 ..
位置
自定义对象:
- (id)initWithValue:(NSString *)value {
if ((self = [super init])) {
self.locationId = [value valueForKeyPath:@"locationId"];
self.companyName = [value valueForKeyPath:@"companyName"];
self.street1 = [value valueForKeyPath:@"street1"];
self.street2 = [value valueForKeyPath:@"street2"];
self.suburb = [value valueForKeyPath:@"suburb"];
self.state = [value valueForKeyPath:@"state"];
self.postcode = [value valueForKeyPath:@"postcode"];
self.phoneNo = [value valueForKeyPath:@"phoneNo"];
self.latitude = [value valueForKeyPath:@"latitude"];
self.longitude = [value valueForKeyPath:@"longitude"];
}
return self;
}
- (void)dealloc {
[super dealloc];
locationId = nil;
companyName = nil;
street1 = nil;
street2 = nil;
suburb = nil;
state = nil;
postcode = nil;
phoneNo = nil;
latitude = nil;
longitude = nil;
}
When should I be releasing [self.activeLocations]
, which is an NSMutableArray
inside my custom object? I am also getting memory leaks in initWithValue
.
Also the Location
object below. Am I calling this and releasing this properly?
Method in Custom Object.m:
- (id)initWithValue:(NSString *)value {
if ((self = [super init])) {
self.couponId = [value valueForKey:@"couponId"];
self.couponName = [value valueForKeyPath:@"couponName"];
self.qrCode = [value valueForKeyPath:@"description"];
self.companyName = [value valueForKeyPath:@"companyName"];
self.categoryName = [value valueForKeyPath:@"categoryName"];
self.distance = [value valueForKeyPath:@"distance"];
NSDictionary *activeLocationsDict = [value valueForKeyPath:@"activeLocations"];
//self.activeLocations = [[[NSMutableArray alloc] init] autorelease];
self.activeLocations = [NSMutableArray array];
for (id val in activeLocationsDict) {
// Add JSON objects to array.
Location *l = [[Location alloc] initWithValue:val];
[self.activeLocations addObject:l];
[l release];
}
}
return self;
}
- (void)dealloc {
[super dealloc];
couponId = nil;
couponName = nil;
qrCode = nil;
companyName = nil;
categoryName = nil;
distance = nil;
activeLocations = nil;
}
My Custom Object.h
@interface Coupon : NSObject {
NSNumber *couponId;
NSString *couponName;
NSString *qrCode;
NSString *companyName;
NSString *categoryName;
NSString *distance;
NSMutableArray *activeLocations;
}
@property (nonatomic, copy) NSNumber *couponId;
@property (nonatomic, copy) NSString *couponName;
@property (nonatomic, copy) NSString *qrCode;
@property (nonatomic, copy) NSString *companyName;
@property (nonatomic, copy) NSString *categoryName;
@property (nonatomic, copy) NSString *distance;
@property (nonatomic, retain) NSMutableArray *activeLocations;
- (id)initWithValue:(NSString *)value;
This is how I'm using the above initWithValue
:
- (NSMutableArray *)createArrayOfCoupons:(NSString *)value {
NSDictionary *responseJSON = [value JSONValue];
// Loop through key value pairs in JSON response.
//NSMutableArray *couponsArray = [[NSMutableArray alloc] init] autorelease];
NSMutableArray *couponsArray = [NSMutableArray array];
for (id val in responseJSON) {
// Add JSON objects to array.
Coupon *c = [[Coupon alloc] initWithValue:val];
[couponsArray addObject:c];
[c release];
}
return couponsArray;
}
I get memory leaks on initWithValue
in the above method as well...
Location
Custom Object:
- (id)initWithValue:(NSString *)value {
if ((self = [super init])) {
self.locationId = [value valueForKeyPath:@"locationId"];
self.companyName = [value valueForKeyPath:@"companyName"];
self.street1 = [value valueForKeyPath:@"street1"];
self.street2 = [value valueForKeyPath:@"street2"];
self.suburb = [value valueForKeyPath:@"suburb"];
self.state = [value valueForKeyPath:@"state"];
self.postcode = [value valueForKeyPath:@"postcode"];
self.phoneNo = [value valueForKeyPath:@"phoneNo"];
self.latitude = [value valueForKeyPath:@"latitude"];
self.longitude = [value valueForKeyPath:@"longitude"];
}
return self;
}
- (void)dealloc {
[super dealloc];
locationId = nil;
companyName = nil;
street1 = nil;
street2 = nil;
suburb = nil;
state = nil;
postcode = nil;
phoneNo = nil;
latitude = nil;
longitude = nil;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
摆脱这个。它什么也不做。
您应该使用一种特定的模式进行初始化:
最后,为了回答您的实际问题,假设您在属性中使用
retain
,那么您需要释放两个位置。这是第一个:
为什么:
[[NSMutableArray alloc] init]
使您的代码通过保留该对象来拥有该对象。但该财产集也通过保留它来声明所有权。您并不真的希望此NSMutableArray
由代码和您的自定义对象拥有,您希望它由您的对象拥有。我的建议是只使用这个:
第二个地方是在你的 dealloc 中:(
就我个人而言,我一直在考虑是否在 dealloc 中使用点符号而不是
[activeLocations release];
。我我现在倾向于使用该属性将所有内存管理规则设置为 nil,这会将所有内存管理规则放在一个位置。)Apple 有一份关于内存管理的精彩文档,您应该阅读:内存管理编程指南:对象所有权和处置。
Get rid of this. It does nothing.
There's a specific pattern you should use for initialization:
Finally, to answer your actual question, assuming you're using
retain
with your property, there's two places you'll need to release.Here's the first:
Why:
[[NSMutableArray alloc] init]
makes your code own the object by retaining it. But the property set also claims ownership by retaining it. You don't really want thisNSMutableArray
owned by the code and your custom object, you want it owned by your object.My suggestion is to just use this:
The second place is in your dealloc:
(Personally, I've gone back and forth on whether to use dot notation in dealloc rather than
[activeLocations release];
. I'm favouring setting to nil using the property now, which puts all the memory management rules in a single location.)Apple has a great document on memory management you should read: Memory Management Programming Guide: Object Ownership and Disposal.
首先,你重写的
-init
方法完全没有必要,因为默认情况下,当调用一个方法时,运行时会执行继承层次结构的向上遍历,直到指定的方法找到了,所以它会找到NSObject
的-init
方法并调用它。其次,您应该在覆盖的
-dealloccopy
或retain
的属性)调用release
代码>方法。第三,在您的情况下,当您调用传递本地已拥有的对象的属性 setter 时,您必须在调用 setter 后向该对象发送
release
消息,以正确地将对象的所有权移交给接收器。有两种方法可以做到这一点:
一种方法是使用
alloc
、copy
或new
创建您拥有的对象,然后调用属性设置器,传入该对象,然后向其发送release
消息。另一种方法是将自动释放的对象传递给属性设置器,然后属性设置器将
保留
或复制
其参数,从而获得所有权First of all, your overridden
-init
method is completely unnecessary because by default when a method is invoked, the runtime will perform an upward traversal of the inheritance hierarchy until the specified method is found, so it will findNSObject
's-init
method and invoke it.Second, you should invoke
release
on all of your owned properties (ones withcopy
orretain
) in your overridden-dealloc
method.Third, in your case, when you call the property setter passing in an object that is already owned locally, you must send the object the
release
message after invoking the setter to correctly hand off ownership of the object to the receiver.There are two ways to do this:
One way is to create an object that you own using
alloc
,copy
ornew
, and then invoke the property setter, passing in that object, then send it therelease
message.Another way is to pass in an autoreleased object to the property setter, which will then
retain
orcopy
its argument and thereby obtain ownership何时应该释放它的答案是 activeLocations 数组和该数组中的所有元素(记住数组中的每个元素都由数组本身保留)是否是必需的问题Location 对象的生命周期。
如果您将 activeLocations 数组用于某些临时目的,例如在方法或方法链中,则不再需要它,或者您计划在下次需要时刷新其成员,那么这是有意义的当您使用完数组(及其元素,这是自动的)后,在最后使用该数组的任何函数中释放该数组。您将使用约定
self.activeLocations = nil;
来让运行时系统释放数组并将成员设置为 nil。
另一方面,如果 activeLocations 数组数据对于 Locations 对象的功能是必需的,并且只要 Location 对象存在就必须存在,那么您将需要在 Location 对象的 dealloc 方法中释放该数组,例如:
碰巧的是,您几乎总是希望在 dealloc 方法中释放成员对象,例如 activeLocations。这确保了当 Location 对象被释放时,它包含的成员被清除。请记住,Objective-C 不会调用空指针上的方法,因此如果您之前将 activeLocations 设置为 nil,则 dealloc 中的调用是安全的无操作。
鉴于您总是会在 dealloc 中将事物设置为释放,现在您实际上只需要问自己是否需要在对象生命周期中的某个位置释放/重新创建阶段(同样,由使用频率要求决定)。
The answer to when you should be releasing it is a question of whether or not the activeLocations array and all the elements in that array (remember each element in the array is retained by the array itself) are necessary throughout the lifetime of the Location object.
If you use the activeLocations array for some temporary purpose, for example in a method or chain of methods, then don't need it again, or you plan to refresh its members at some later time when you need it next, then it makes sense to release the array (and its elements, which is automatic) when you're done using it, in whatever function last uses the array. You will use the convention
self.activeLocations = nil;
to let the runtime system release the array and set the member to nil.
If, on the other hand, the activeLocations array data is mandatory for the Locations object to function and must exist as long as the Location object exists, then you will want to release the array inside the dealloc method of the Location object, for example:
As it happens, you're pretty much always going to want to release member objects such as activeLocations in a dealloc method. This ensures that when the Location object is released the members it contains are cleaned up. Remember that Objective-C does not call methods on null pointers, so if you have previously set activeLocations to nil the call in dealloc is a safe no-op.
Given then that you'll always set things up to release in dealloc, now you really just have to ask yourself if you need a release/recreate phase somewhere in your object lifecycle (again, determined by frequency-of-use requirements).
这取决于你要问什么。在您共享的 initWithValue: 方法中,您双重保留了数组。它应该在 initWithValue: 内释放或自动释放一次。
应在自定义对象的 dealloc 方法中第二次释放该数组。
It depends on what you're asking. In the initWithValue: method that you've shared, you are double-retaining the array. It should be released or autoreleased once within initWithValue:.
The array should be released a second time in the custom object's dealloc method.