iPhone - 自定义对象内的 NSMutableArray。什么时候发布?

发布于 2024-10-15 07:03:22 字数 3782 浏览 3 评论 0原文

我应该什么时候释放[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...

enter image description here

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

红焚 2024-10-22 07:03:22
- (id)init {
   ....
}

摆脱这个。它什么也不做。

- (id)initWithValue:(NSString *)value {
    [super init];

您应该使用一种特定的模式进行初始化:

- (id)initWithValue:(NSString *)value {
    if (( self = [super init] )) {
      // everything except the return
    }
    return self;
}

最后,为了回答您的实际问题,假设您在属性中使用 retain ,那么您需要释放两个位置。

这是第一个:

self.activeLocations = [[NSMutableArray alloc] init];

为什么[[NSMutableArray alloc] init] 使您的代码通过保留该对象来拥有该对象。但该财产集也通过保留它来声明所有权。您并不真的希望此 NSMutableArray 由代码和您的自定义对象拥有,您希望它由您的对象拥有。

我的建议是只使用这个:

self.activeLocations = [NSMutableArray array];

第二个地方是在你的 dealloc 中:(

- (void)dealloc {
    self.activeLocations = nil;

    // ...and everything else you've set as a property using retain

    [super dealloc];
}

就我个人而言,我一直在考虑是否在 dealloc 中使用点符号而不是 [activeLocations release];。我我现在倾向于使用该属性将所有内存管理规则设置为 nil,这会将所有内存管理规则放在一个位置。)

Apple 有一份关于内存管理的精彩文档,您应该阅读:内存管理编程指南:对象所有权和处置。

- (id)init {
   ....
}

Get rid of this. It does nothing.

- (id)initWithValue:(NSString *)value {
    [super init];

There's a specific pattern you should use for initialization:

- (id)initWithValue:(NSString *)value {
    if (( self = [super init] )) {
      // everything except the return
    }
    return self;
}

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:

self.activeLocations = [[NSMutableArray alloc] init];

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 this NSMutableArray owned by the code and your custom object, you want it owned by your object.

My suggestion is to just use this:

self.activeLocations = [NSMutableArray array];

The second place is in your dealloc:

- (void)dealloc {
    self.activeLocations = nil;

    // ...and everything else you've set as a property using retain

    [super 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.

花桑 2024-10-22 07:03:22

首先,你重写的 -init 方法完全没有必要,因为默认情况下,当调用一个方法时,运行时会执行继承层次结构的向上遍历,直到指定的方法找到了,所以它会找到NSObject-init方法并调用它。

其次,您应该在覆盖的 -dealloccopyretain 的属性)调用 release代码>方法。

第三,在您的情况下,当您调用传递本地已拥有的对象的属性 setter 时,您必须在调用 setter 后向该对象发送 release 消息,以正确地将对象的所有权移交给接收器。

有两种方法可以做到这一点:

一种方法是使用 alloccopynew 创建您拥有的对象,然后调用属性设置器,传入该对象,然后向其发送 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 find NSObject's -init method and invoke it.

Second, you should invoke release on all of your owned properties (ones with copy or retain) 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 or new, and then invoke the property setter, passing in that object, then send it the release message.

Another way is to pass in an autoreleased object to the property setter, which will then retain or copy its argument and thereby obtain ownership

左耳近心 2024-10-22 07:03:22

何时应该释放它的答案是 activeLocations 数组和该数组中的所有元素(记住数组中的每个元素都由数组本身保留)是否是必需的问题Location 对象的生命周期。

如果您将 activeLocations 数组用于某些临时目的,例如在方法或方法链中,则不再需要它,或者您计划在下次需要时刷新其成员,那么这是有意义的当您使用完数组(及其元素,这是自动的)后,在最后使用该数组的任何函数中释放该数组。您将使用约定

self.activeLocations = nil;

来让运行时系统释放数组并将成员设置为 nil。

另一方面,如果 activeLocations 数组数据对于 Locations 对象的功能是必需的,并且只要 Location 对象存在就必须存在,那么您将需要在 Location 对象的 dealloc 方法中释放该数组,例如:

- (void) dealloc {
    [activeLocations release];

    [super 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:

- (void) dealloc {
    [activeLocations release];

    [super dealloc];
}

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).

不醒的梦 2024-10-22 07:03:22

这取决于你要问什么。在您共享的 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文