Skip to content

Instantly share code, notes, and snippets.

@beccadax
Created August 26, 2012 02:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beccadax/3473115 to your computer and use it in GitHub Desktop.
Save beccadax/3473115 to your computer and use it in GitHub Desktop.
Suggested code to get rid of objects with no references except for their presence in a specific set
// self.resources is an NSMutableSet of ANResource objects.
// I want to remove the objects that have no other references in the app.
// (This is intended to be called in response to an iOS memory warning.)
// Will this do the trick?
- (void)discardUnusedResources {
// We pass the objects through a weak reference; if they're not
// referenced anywhere else in the app, they won't survive the journey.
NSMutableSet * newResources = [NSMutableSet new];
NSUInteger oldResourceCount = self.resources.count;
__weak ANResource * weakResource;
while((weakResource = [self.resources anyObject])) {
[self.resources removeObject:weakResource];
__strong ANResource * strongResource = weakResource;
if(strongResource) {
[newResources addObject:strongResource];
}
}
self.resources = newResources;
NSLog(@"-[ANSession discardUnusedResources]: started with %u resources, ended with %u", oldResourceCount, self.resources.count);
}
@aufflick
Copy link

ok how about this - use both a weak NSHashTable and a strong NSSet. When you set objects into your cache, add them to both sets. When you get memory pressure, call removeAllObjects on the NSSet. When you read from your cache, always read from the hash table. You never really need to remove objects from the NSHashTable since whether the key doesn't exist or it has been release, nil will be the result, and you don't care about exactly when weak objects will be reaped. (If you're worried about your hash table getting massive, you could just prune any nil values either periodically or on every X calls to your cache api).

@belkadan
Copy link

No one here's heard of NSCache?

@beccadax
Copy link
Author

@belkadan, NSCache drops the entire cache on the floor under memory pressure. That's not what I want—it would lose references to objects that are still active. The main purpose of this set is not caching, but uniquing—ensuring that each of the external resources is represented by exactly one ANResource object. (Think of the way a Core Data managed object context always has exactly one object for each record—that's what I'm doing.) If I used NSCache, then a cache drop could cause a new object to be created for a resource which already has an old object, and the old object would slowly become staler and staler.

I'm using an NSHashTable for now, but I'm not really happy with that solution, because I want this code to run on iOS 5 as well as 6...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment