开发者

Proper, memory-managed implementation of custom NSDictionary getter

开发者 https://www.devze.com 2023-04-12 17:58 出处:网络
Thanks in advance... So after some recent memory leaks and bugs (documented here), I\'ve been studying up on my memory management, and I am now trying to write a custom getter for an NSDictionary in

Thanks in advance...

So after some recent memory leaks and bugs (documented here), I've been studying up on my memory management, and I am now trying to write a custom getter for an NSDictionary in a helper class I have.

The reasons for the custom getter are:

First, it's a calculated dictionary, so for performance issues I want to return the cached object unless it's necessary to regenerate it (my example below isn't too computationally expensive, but others in the class will be).

Second, I want to lazily instantiate. I only want to generate the dictionary if another class "asks" for it, which is why I'm checking for nil in the getter.

So, the questions. The code below represents my first ever (studied) attempt at writing custom setter/getter, I usually just synthesize.

1) Is this proper implementation and proper memory management?

2) Is this best?

3) Is the BOOL installedStandardsChangedSinceLast开发者_开发技巧Read the best way to flag the need to recalculate? This would happen if other methods in the class had changed something. But should I just have those methods nil out _installedStandards instead, since that would also trigger the recalculate?

4) Finally, if I did just have the other methods nil out the iVar to flag it for recalculation, how would I make sure I don't leak? Would I use the setter (i.e. self.installedStandards = nil), nil the iVar directly (i.e. _installedStandards = nil), or something else?

(Oh, and if I nil'd the iVar directly, would I need to release it first? It seems like correct would be [_installedStandards release]; _installedStandards = nil? In which case couldn't I just use self.installedStandards = nil?)

Onto the code! Reminder that this is a simplified version of what will be a more complex class (see link at top) with lots of these setters/getters. I need to make sure I'm executing properly before I flesh it out.

.h file

@interface InstalledStandardTracker20 : NSObject {

    NSDictionary *_installedStandards;
    BOOL _installedStandardsChangedSinceLastRead;
}

@property (nonatomic, retain) NSDictionary *installedStandards;
@property (nonatomic) BOOL installedStandardsChangedSinceLastRead;

@end

@implementation

@implementation InstalledStandardTracker20

@synthesize installedStandardsChangedSinceLastRead = _installedStandardsChangedSinceLastRead;

- (void)refreshInstalledStandards {
    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
    self.installedStandards = [currentDefaults objectForKey:@"installedStandards"];
    self.installedStandardsChangedSinceLastRead = NO;
}

- (NSDictionary *)installedStandards {
    if (!_installedStandards || self.installedStandardsChangedSinceLastRead) {
        [self refreshInstalledStandards];
    }
    return _installedStandards;
}

- (void)setInstalledStandards:(NSDictionary *)newInstalledStandards {
    [newInstalledStandards retain];
    [_installedStandards release];
    _installedStandards = newInstalledStandards;
}


This question is rather difficult to answer because there is no context outside of the class. The code appears to be memory-leak free. Also, you don't need to implement -setInstalledStandards:. Since you call @synthesize on a retain property, the generated setter would look just like that. In essence, you're overriding the method with exactly the same method.

For your other question, nilling out an iVar has nothing to do with what objects are being held in memory. As soon as you release the iVar, the object at the memory address contained in your pointer is no longer guaranteed to exist. By nilling the iVar, you are simply resetting that memory address to point to nil. This avoids you getting an EXC_BAD_ACCESS runtime exception because no other parts of your program will attempt to access this now undefined address space.

In essence, you always have to release it. While nilling it is good practice, it is not required so long as you don't try to access that pointer until you know it contains a valid object in memory. I hope that makes sense.

0

精彩评论

暂无评论...
验证码 换一张
取 消