給oschina iPhone客戶端加了一個頭象緩存

今天閱讀oschina iPhone客戶端,發如今問答頁面,每次刷新都會從新請求用戶的頭象,即便在頂部的tab之間來回切換,也會屢次重複請求,這其實能夠徹底用緩存來避免的。之前寫過一個圖片緩存類,因此就加到oschina 的iphone客戶端裏面了,發了一個pull request。地址是:https://github.com/oschina/iphone-app/pull/2/filesgit

這個圖片緩存類很簡單,可是挺實用的,推薦給你們:github

//
//  TQImageCAche.h
//
//
//  Created by Tang Qiao on 12-5-9.
//  Copyright (c) 2012年 blog.devtang.com. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef enum {
    kLastCacheKitStatusNotFound,
    kLastCacheKitStatusInMemory,
    kLastCacheKitStatusInDisk
} LastCacheKitStatus;

@interface  TQImageCache : NSObject

@property (nonatomic, assign) NSInteger maxMemoryCacheNumber;
@property (nonatomic, assign) LastCacheKitStatus lastCacheKitStatus;
@property (nonatomic, retain) NSString * cachePath;


- (id) initWithCachePath:(NSString*)path andMaxMemoryCacheNumber:(NSInteger)maxNumber;

- (void) putImage:(NSData *) imageData withName:(NSString*)imageName ;
- (NSData *) getImage:(NSString *)imageName;
- (void)clear;

+ (NSString *)parseUrlForCacheName:(NSString *)name;

@end


//
//  TQImageCache.m
//
//
//  Created by Tang Qiao on 12-5-9.
//  Copyright (c) 2012年 blog.devtang.com. All rights reserved.
//

#import "TQImageCache.h"

@interface  TQImageCache()

@property (nonatomic, retain) NSFileManager * fileManager;
@property (nonatomic, retain) NSMutableDictionary * memoryCache;
@property (nonatomic, retain) NSMutableArray *memoryCacheKeys;

@end 

#define PATH_OF_TEMP        [NSHomeDirectory() stringByAppendingPathComponent:@"tmp"]

@implementation TQImageCache;

static BOOL debugMode = NO;

- (id) init {
    return [self initWithCachePath:@"TQImageCache" andMaxMemoryCacheNumber:50];
}

- (id) initWithCachePath:(NSString*)path andMaxMemoryCacheNumber:(NSInteger)maxNumber {
    NSString * tmpDir = PATH_OF_TEMP;
    if ([path hasPrefix:tmpDir]) {
        _cachePath = path;
    } else {
        if ([path length] != 0) {
            _cachePath = [tmpDir stringByAppendingPathComponent:path];
        } else {
            return nil;
        }
    }
    _maxMemoryCacheNumber = maxNumber;

    if (self = [super init]) {
        _fileManager = [NSFileManager defaultManager];
        if ([_fileManager fileExistsAtPath:_cachePath isDirectory:nil] == NO) {
            // create the directory
            BOOL res = [_fileManager createDirectoryAtPath:_cachePath withIntermediateDirectories:YES attributes:nil error:nil];
            if (!res) {
                debugLog(@"file cache directory create failed! The path is %@", _cachePath);
                return nil;
            }
        }
        _memoryCache = [[NSMutableDictionary alloc] initWithCapacity:_maxMemoryCacheNumber + 1];
        _memoryCacheKeys = [[NSMutableArray alloc] initWithCapacity:_maxMemoryCacheNumber + 1];
        return self;
    }
    return nil;
}

- (void)clear {
    _memoryCache = [[NSMutableDictionary alloc] initWithCapacity:_maxMemoryCacheNumber + 1];
    _memoryCacheKeys = [[NSMutableArray alloc] initWithCapacity:_maxMemoryCacheNumber + 1];

    // remove all the file in temporary
    NSArray * files = [self.fileManager contentsOfDirectoryAtPath:self.cachePath error:nil];
    for (NSString * file in files) {
        if (debugMode) {
            debugLog(@"remove cache file: %@", file);
        }
        [self.fileManager removeItemAtPath:file error:nil];
    }
}

- (void) checkCacheSize {
    if ([self.memoryCache count] > _maxMemoryCacheNumber) {
        NSString * key = [self.memoryCacheKeys objectAtIndex:0];
        [self.memoryCache removeObjectForKey:key];
        [self.memoryCacheKeys removeObjectAtIndex:0];
        if (debugMode) {
            debugLog(@"remove oldest cache from memory: %@", key);
        }
    }
}

- (void) putImage:(NSData *) imageData withName:(NSString*)imageName {
    if (imageData == nil) {
        if (debugMode) {
            debugLog(@"image data is nil");
        }
        return;
    }
    [self.memoryCache setObject:imageData forKey:imageName];
    [self.memoryCacheKeys addObject:imageName];
    [self checkCacheSize];
    NSString * path = [self.cachePath stringByAppendingPathComponent:imageName];
    [imageData writeToFile:path atomically:YES];
    if (debugMode) {
        debugLog(@"TQImageCache put cache image to %@", path);
    }
}

- (NSData *) getImage:(NSString *)imageName {
    NSData * data = [self.memoryCache objectForKey:imageName];
    if (data != nil) {
        if (debugMode) {
            debugLog(@"TQImageCache hit cache from memory: %@", imageName);
        }
        self.lastCacheKitStatus = kLastCacheKitStatusInMemory;
        return data;
    }
    NSString * path = [self.cachePath stringByAppendingPathComponent:imageName];
    if ([self.fileManager fileExistsAtPath:path]) {
        if (debugMode) {
            debugLog(@"TQImageCache hit cache from file %@", path);
        }
        data = [NSData dataWithContentsOfFile:path];
        // put it to memeory
        [self.memoryCache setObject:data forKey:imageName];
        [self.memoryCacheKeys addObject:imageName];
        [self checkCacheSize];
        self.lastCacheKitStatus = kLastCacheKitStatusInDisk;
        return data;
    }
    self.lastCacheKitStatus = kLastCacheKitStatusNotFound;
    return nil;
}


+ (NSString *)parseUrlForCacheName:(NSString *)name {
    if (name == nil) {
        return nil;
    }
    name = [name stringByReplacingOccurrencesOfString:@"http://" withString:@""];
    name = [name stringByReplacingOccurrencesOfString:@"://" withString:@"-"];
    name = [name stringByReplacingOccurrencesOfString:@"/" withString:@"-"];
    name = [NSString stringWithFormat:@"%@.png", name];
    // debugLog(@"dest video url cache name :%@", name);
    return name;
}


@end


另外發現源碼中的全部NSLog都被註釋掉了,其實徹底沒必要這樣,只須要加上下面這個宏,就能夠在調試的時候輸出log,在真正打包線上版本時去掉log。緩存

 

#ifdef DEBUG
#define debugLog(...) NSLog(__VA_ARGS__)
#define debugMethod() NSLog(@"%s", __func__)
#else
#define debugLog(...)
#define debugMethod()
#endif


一併修改發了一個pull request。app

 

打算天天晚上有空都閱讀一點代碼,看能學到些什麼,或者能改進些什麼。iphone

相關文章
相關標籤/搜索