Skip to content

Commit 8b01404

Browse files
author
Mallory Paine
committed
Bring back manual memory management <3
1 parent ab6f966 commit 8b01404

File tree

10 files changed

+125
-40
lines changed

10 files changed

+125
-40
lines changed

FastImageCache/FICImageCache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ typedef void (^FICImageRequestCompletionBlock)(UIImage *sourceImage);
3434
@discussion The delegate is responsible for asynchronously providing the source image for an entity. Optionally, the delegate can require that all formats in a format
3535
family for a particular entity be processed. Any errors that occur in the image cache are also communicated back to the delegate.
3636
*/
37-
@property (nonatomic, weak) id <FICImageCacheDelegate> delegate;
37+
@property(nonatomic, assign) id <FICImageCacheDelegate> delegate;
3838

3939
///---------------------------------------
4040
/// @name Accessing the Shared Image Cache

FastImageCache/FICImageCache.m

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ @interface FICImageCache () {
2525
NSMutableDictionary *_formats;
2626
NSMutableDictionary *_imageTables;
2727
NSMutableDictionary *_requests;
28-
__weak id <FICImageCacheDelegate> _delegate;
28+
id <FICImageCacheDelegate> _delegate;
2929

3030
BOOL _delegateImplementsShouldProcessAllFormatsInFamilyForEntity;
3131
BOOL _delegateImplementsErrorDidOccurWithMessage;
@@ -87,6 +87,14 @@ - (id)init {
8787
return self;
8888
}
8989

90+
- (void)dealloc {
91+
[_formats release];
92+
[_imageTables release];
93+
[_requests release];
94+
95+
[super dealloc];
96+
}
97+
9098
#pragma mark - Working with Formats
9199

92100
- (void)setFormats:(NSArray *)formats {
@@ -102,6 +110,7 @@ - (void)setFormats:(NSArray *)formats {
102110
// Only initialize an image table for this format if it is needed on the current device.
103111
FICImageTable *imageTable = [[FICImageTable alloc] initWithFormat:imageFormat];
104112
[_imageTables setObject:imageTable forKey:formatName];
113+
[imageTable release];
105114
[_formats setObject:imageFormat forKey:formatName];
106115

107116
[imageTableFiles addObject:[[imageTable tableFilePath] lastPathComponent]];
@@ -139,7 +148,7 @@ - (NSArray *)formatsWithFamily:(NSString *)family {
139148
}
140149
}
141150

142-
return [formats copy];
151+
return [[formats copy] autorelease];
143152
}
144153

145154
#pragma mark - Retrieving Images
@@ -170,6 +179,8 @@ - (BOOL)_retrieveImageForEntity:(id <FICEntity>)entity withFormatName:(NSString
170179
completionBlock(entity, formatName, image);
171180
});
172181
}
182+
183+
[image release]; // Already retained by the block
173184
});
174185
} else {
175186
UIImage *image = [imageTable newImageForEntityUUID:entityUUID sourceImageUUID:sourceImageUUID preheatData:NO];
@@ -185,6 +196,8 @@ - (BOOL)_retrieveImageForEntity:(id <FICEntity>)entity withFormatName:(NSString
185196
});
186197
}
187198
}
199+
200+
[image release]; // Already retained by the block
188201
};
189202

190203
if (image == nil && _delegate != nil) {
@@ -262,7 +275,7 @@ static void _FICAddCompletionBlockForEntity(NSString *formatName, NSMutableDicti
262275
[completionBlocks setObject:blocksArray forKey:formatName];
263276
}
264277

265-
FICImageCacheCompletionBlock completionBlockCopy = [completionBlock copy];
278+
FICImageCacheCompletionBlock completionBlockCopy = [[completionBlock copy] autorelease];
266279
[blocksArray addObject:completionBlockCopy];
267280
}
268281
}
@@ -274,7 +287,7 @@ - (void)setImage:(UIImage *)image forEntity:(id <FICEntity>)entity withFormatNam
274287
NSDictionary *completionBlocksDictionary = nil;
275288

276289
if (completionBlock != nil) {
277-
completionBlocksDictionary = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:[completionBlock copy]] forKey:formatName];
290+
completionBlocksDictionary = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:[[completionBlock copy] autorelease]] forKey:formatName];
278291
}
279292

280293
NSString *entityUUID = [entity UUID];
@@ -348,6 +361,8 @@ - (void)_processImage:(UIImage *)image forEntity:(id <FICEntity>)entity imageTab
348361
}
349362
});
350363
}
364+
365+
[resultImage release];
351366
});
352367
}
353368
}

FastImageCache/FICImageFormat.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ - (BOOL)isGrayscale {
127127
#pragma mark - Object Lifecycle
128128

129129
+ (instancetype)formatWithName:(NSString *)name family:(NSString *)family imageSize:(CGSize)imageSize style:(FICImageFormatStyle)style maximumCount:(NSInteger)maximumCount devices:(FICImageFormatDevices)devices {
130-
FICImageFormat *imageFormat = [[FICImageFormat alloc] init];
130+
FICImageFormat *imageFormat = [[[FICImageFormat alloc] init] autorelease];
131131

132132
[imageFormat setName:name];
133133
[imageFormat setFamily:family];
@@ -139,6 +139,13 @@ + (instancetype)formatWithName:(NSString *)name family:(NSString *)family imageS
139139
return imageFormat;
140140
}
141141

142+
- (void)dealloc {
143+
[_name release];
144+
[_family release];
145+
146+
[super dealloc];
147+
}
148+
142149
#pragma mark - Working with Dictionary Representations
143150

144151
- (NSDictionary *)dictionaryRepresentation {

FastImageCache/FICImageTable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ extern NSString *const FICImageTableScreenScaleKey;
4242
/**
4343
The image format that describes the image table.
4444
*/
45-
@property (nonatomic, strong, readonly) FICImageFormat *imageFormat;
45+
@property (nonatomic, retain, readonly) FICImageFormat *imageFormat;
4646

4747
///-----------------------------------------------
4848
/// @name Accessing Information about Image Tables

FastImageCache/FICImageTable.m

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ @interface FICImageTable () {
5252

5353
NSMutableDictionary *_chunkDictionary;
5454
NSCountedSet *_chunkSet;
55-
55+
5656
NSRecursiveLock *_lock;
5757
CFMutableDictionaryRef _indexNumbers;
5858

@@ -108,9 +108,9 @@ + (NSString *)directoryPath {
108108
static dispatch_once_t onceToken;
109109
dispatch_once(&onceToken, ^{
110110
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
111-
__directoryPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"ImageTables"];
111+
__directoryPath = [[[paths objectAtIndex:0] stringByAppendingPathComponent:@"ImageTables"] retain];
112112

113-
NSFileManager *fileManager = [[NSFileManager alloc] init];
113+
NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
114114
BOOL directoryExists = [fileManager fileExistsAtPath:__directoryPath];
115115
if (directoryExists == NO) {
116116
[fileManager createDirectoryAtPath:__directoryPath withIntermediateDirectories:YES attributes:nil error:nil];
@@ -134,7 +134,7 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat {
134134
_indexNumbers = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
135135

136136
_imageFormat = [imageFormat copy];
137-
_imageFormatDictionary = [imageFormat dictionaryRepresentation];
137+
_imageFormatDictionary = [[imageFormat dictionaryRepresentation] retain];
138138

139139
_screenScale = [[UIScreen mainScreen] scale];
140140

@@ -145,12 +145,12 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat {
145145

146146
_chunkDictionary = [[NSMutableDictionary alloc] init];
147147
_chunkSet = [[NSCountedSet alloc] init];
148-
148+
149149
_indexMap = [[NSMutableDictionary alloc] init];
150150
_occupiedIndexes = [[NSMutableIndexSet alloc] init];
151151

152152
_MRUEntries = [[NSMutableOrderedSet alloc] init];
153-
_inUseEntries = [NSCountedSet set];
153+
_inUseEntries = [[NSCountedSet alloc] init];
154154

155155
_sourceImageMap = [[NSMutableDictionary alloc] init];
156156

@@ -188,7 +188,8 @@ - (instancetype)initWithFormat:(FICImageFormat *)imageFormat {
188188
// If something goes wrong and we can't open the image table file, then we have no choice but to release and nil self.
189189
NSString *message = [NSString stringWithFormat:@"*** FIC Error: %s could not open the image table file at path %@. The image table was not created.", __PRETTY_FUNCTION__, _filePath];
190190
[[FICImageCache sharedImageCache] _logMessage:message];
191-
191+
192+
[self release];
192193
self = nil;
193194
}
194195
}
@@ -201,9 +202,24 @@ - (instancetype)init {
201202
}
202203

203204
- (void)dealloc {
205+
[_imageFormat release];
206+
[_filePath release];
207+
208+
[_indexMap release];
209+
[_occupiedIndexes release];
210+
[_MRUEntries release];
211+
[_sourceImageMap release];
212+
[_imageFormatDictionary release];
213+
[_chunkDictionary release];
214+
[_chunkSet release];
215+
204216
if (_fileDescriptor >= 0) {
205217
close(_fileDescriptor);
206218
}
219+
220+
[_lock release];
221+
222+
[super dealloc];
207223
}
208224

209225
#pragma mark - Working with Chunks
@@ -225,7 +241,7 @@ - (FICImageTableChunk *)_chunkAtIndex:(NSInteger)index {
225241
FICImageTableChunk *chunk = nil;
226242

227243
if (index < _chunkCount) {
228-
chunk = [self _cachedChunkAtIndex:index];
244+
chunk = [[self _cachedChunkAtIndex:index] retain];
229245

230246
if (chunk == nil) {
231247
size_t chunkLength = _chunkLength;
@@ -234,7 +250,7 @@ - (FICImageTableChunk *)_chunkAtIndex:(NSInteger)index {
234250
chunkLength = (size_t)(_fileLength - chunkOffset);
235251
}
236252

237-
chunk = [[FICImageTableChunk alloc] initWithFileDescriptor:_fileDescriptor index:index length:chunkLength];
253+
chunk = [[FICImageTableChunk alloc] initWithImageTable:self fileDescriptor:_fileDescriptor index:index length:chunkLength];
238254
[self _setChunk:chunk index:index];
239255
}
240256
}
@@ -244,7 +260,15 @@ - (FICImageTableChunk *)_chunkAtIndex:(NSInteger)index {
244260
[[FICImageCache sharedImageCache] _logMessage:message];
245261
}
246262

247-
return chunk;
263+
return [chunk autorelease];
264+
}
265+
266+
- (void)_chunkWillBeDeallocated:(FICImageTableChunk *)chunk {
267+
[_lock lock];
268+
269+
[self _setChunk:nil index:[chunk index]];
270+
271+
[_lock unlock];
248272
}
249273

250274
#pragma mark - Storing, Retrieving, and Deleting Entries
@@ -291,8 +315,6 @@ - (void)setEntryForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSString *
291315
[_lock unlock];
292316

293317
CGContextRef context = CGBitmapContextCreate([entryData bytes], pixelSize.width, pixelSize.height, bitsPerComponent, _imageRowLength, colorSpace, bitmapInfo);
294-
CGColorSpaceRelease(colorSpace);
295-
296318
CGContextTranslateCTM(context, 0, pixelSize.height);
297319
CGContextScaleCTM(context, _screenScale, -_screenScale);
298320

@@ -307,6 +329,7 @@ - (void)setEntryForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSString *
307329
} else {
308330
[_lock unlock];
309331
}
332+
CGColorSpaceRelease(colorSpace);
310333
} else {
311334
[_lock unlock];
312335
}
@@ -334,13 +357,15 @@ - (UIImage *)newImageForEntityUUID:(NSString *)entityUUID sourceImageUUID:(NSStr
334357
} else {
335358
[self _entryWasAccessedWithEntityUUID:entityUUID];
336359

360+
[entryData retain]; // Released by _FICReleaseImageData
361+
337362
// Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.
338-
CGDataProviderRef dataProvider = CGDataProviderCreateWithData((__bridge_retained void *)entryData, [entryData bytes], [entryData imageLength], _FICReleaseImageData);
363+
CGDataProviderRef dataProvider = CGDataProviderCreateWithData((void *)entryData, [entryData bytes], [entryData imageLength], _FICReleaseImageData);
339364

340365
[_inUseEntries addObject:entityUUID];
341-
__weak FICImageTable *weakSelf = self;
366+
342367
[entryData executeBlockOnDealloc:^{
343-
[weakSelf removeInUseForEntityUUID:entityUUID];
368+
[self removeInUseForEntityUUID:entityUUID];
344369
}];
345370

346371
CGSize pixelSize = [_imageFormat pixelSize];
@@ -442,7 +467,7 @@ - (int)_maximumCount {
442467
}
443468

444469
- (void)_setEntryCount:(NSInteger)entryCount {
445-
if (entryCount != _entryCount) {
470+
if (entryCount != _entryCount && _entriesPerChunk > 0) {
446471
off_t fileLength = entryCount * _entryLength;
447472
int result = ftruncate(_fileDescriptor, fileLength);
448473

@@ -452,7 +477,7 @@ - (void)_setEntryCount:(NSInteger)entryCount {
452477
} else {
453478
_fileLength = fileLength;
454479
_entryCount = entryCount;
455-
_chunkCount = _entriesPerChunk > 0 ? ((_entryCount + _entriesPerChunk - 1) / _entriesPerChunk) : 0;
480+
_chunkCount = (_entryCount + _entriesPerChunk - 1) / _entriesPerChunk;
456481
}
457482
}
458483
}
@@ -477,9 +502,8 @@ - (FICImageTableEntry *)_entryDataAtIndex:(NSInteger)index {
477502

478503
[_chunkSet addObject:chunk];
479504

480-
__weak FICImageTable *weakSelf = self;
481505
[entryData executeBlockOnDealloc:^{
482-
[weakSelf _entryWasDeallocatedFromChunk:chunk];
506+
[self _entryWasDeallocatedFromChunk:chunk];
483507
}];
484508
}
485509
}
@@ -491,7 +515,7 @@ - (FICImageTableEntry *)_entryDataAtIndex:(NSInteger)index {
491515
[[FICImageCache sharedImageCache] _logMessage:message];
492516
}
493517

494-
return entryData;
518+
return [entryData autorelease];
495519
}
496520

497521
- (void)_entryWasDeallocatedFromChunk:(FICImageTableChunk *)chunk {
@@ -511,6 +535,7 @@ - (NSInteger)_nextEntryIndex {
511535
if (index == NSNotFound) {
512536
index = _entryCount;
513537
}
538+
[unoccupiedIndexes release];
514539

515540
if (index >= [self _maximumCount] && [_MRUEntries count]) {
516541
// Evict the oldest/least-recently accessed entry here
@@ -576,8 +601,10 @@ - (void)_entryWasAccessedWithEntityUUID:(NSString *)entityUUID {
576601
if (index == NSNotFound) {
577602
[_MRUEntries insertObject:entityUUID atIndex:0];
578603
} else if (index != 0) {
604+
[entityUUID retain];
579605
[_MRUEntries removeObjectAtIndex:index];
580606
[_MRUEntries insertObject:entityUUID atIndex:0];
607+
[entityUUID release];
581608
}
582609
}
583610

@@ -602,6 +629,7 @@ - (void)saveMetadata {
602629
if (!entryDict) {
603630
entryDict = [[NSMutableDictionary alloc] init];
604631
[entryMetadata setObject:entryDict forKey:entityUUID];
632+
[entryDict release];
605633
}
606634
NSNumber *tableIndexVal = [_indexMap objectForKey:entityUUID];
607635
NSString *contextUUID = [_sourceImageMap objectForKey:entityUUID];
@@ -616,7 +644,7 @@ - (void)saveMetadata {
616644

617645
NSDictionary *metadataDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
618646
entryMetadata, FICImageTableMetadataKey,
619-
[_imageFormatDictionary copy], FICImageTableFormatKey, nil];
647+
[[_imageFormatDictionary copy] autorelease], FICImageTableFormatKey, nil];
620648

621649
[_lock unlock];
622650

FastImageCache/FICImageTableChunk.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
/**
4444
Initializes a new image table chunk.
45+
46+
@param imageTable The image table to create a chunk from.
4547
4648
@param fileDescriptor The image table's file descriptor to map from.
4749
@@ -51,6 +53,6 @@
5153
5254
@return A new image table chunk.
5355
*/
54-
- (instancetype)initWithFileDescriptor:(int)fileDescriptor index:(NSInteger)index length:(size_t)length;
56+
- (instancetype)initWithImageTable:(FICImageTable *)imageTable fileDescriptor:(int)fileDescriptor index:(NSInteger)index length:(size_t)length;
5557

5658
@end

0 commit comments

Comments
 (0)