文档章节

给oschina iPhone客户端加了一个头象缓存

唐巧
 唐巧
发布于 2012/09/03 23:01
字数 695
阅读 1886
收藏 26

今天阅读oschina iPhone客户端,发现在问答页面,每次刷新都会重新请求用户的头象,即使在顶部的tab之间来回切换,也会多次重复请求,这其实可以完全用缓存来避免的。以前写过一个图片缓存类,所以就加到oschina 的iphone客户端里面了,发了一个pull request。地址是:https://github.com/oschina/iphone-app/pull/2/files

这个图片缓存类很简单,但是挺实用的,推荐给大家:

//
//  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。

 

打算每天晚上有空都阅读一点代码,看能学到些什么,或者能改进些什么。


© 著作权归作者所有

唐巧

唐巧

粉丝 37
博文 1
码字总数 695
作品 0
朝阳
私信 提问
加载中

评论(8)

唐巧
唐巧 博主

引用来自“悠哉悠哉e”的评论

开源项目中用的这个类是你写的?真心不错

是的,过讲了。
悠哉悠哉e
悠哉悠哉e
开源项目中用的这个类是你写的?真心不错
艾欧艾斯
艾欧艾斯
今天看了您写的类,很棒 3q
艾欧艾斯
艾欧艾斯
只能纯支持了
JoeyBlue
JoeyBlue
看了一部分代码,写的挺清晰的,现在刚写iOS,还不能做出什么贡献,呵呵。
junwong
junwong
真的非常感谢
红薯
红薯
看来是其他的界面里有处理头像缓存,问答界面漏掉了 @junwong
红薯
红薯
@junwong 你看看这篇文章,iphone 版不是有头像缓存的吗?
千元悬赏修复 OSC iPhone 客户端在 iOS 7 下的闪退问题

各位 OSCers 们: 应苹果要求在 XCode 5 下重新编译 OSChina 的 iPhone 客户端以兼容 iOS 7,目前我们已经解决了大部分的兼容性问题,但还有一个遗留问题恳请社区的 iOS 开发者们支持。 在 ...

小编辑
2015/07/24
10
1
千元悬赏修复 OSC iPhone 客户端在 iOS 7 下的闪退问题

各位 OSCers 们: 应苹果要求在 XCode 5 下重新编译 OSChina 的 iPhone 客户端以兼容 iOS 7,目前我们已经解决了大部分的兼容性问题,但还有一个遗留问题恳请社区的 iOS 开发者们支持。 在 ...

红薯
2014/01/06
26.8K
112
javaweb入门笔记(2)-http入门

javaweb入门笔记(2)-http入门 标签: javaweb http [TOC] 对HTTP协议早有了解,最近在看javaweb,视频中讲到了这部分,就把视频的内容整理归纳下 请求(Request) 一个完整的HTTP请求包括:一个...

brianway
2016/02/06
253
0
HTTP1.0与HTTP1.1的区别、GET和POST的区别、HTTP响应讲解

HTTP1.0与HTTP1.1的区别 在HTTP1.0中,允许客户端与web服务器建立连接后,只能获得一个web。 在HTTP1.1中,允许客户端与web服务器建立连接后,在一个连接上获取多个资源 HTTP请求 客户端连上...

microcosm1994的博客
2017/12/21
0
0
请务必从官方市场下载 OSC 客户端!!!

今天有两个网友爆料客户端弹广告以及广告推送,包括 Android (详情)和 iPhone 两个客户端(详情)。 OSChina 郑重声明: OSChina 的三个客户端(Android、iPhone 和 WP7 版本)都是开源的,...

oschina
2012/12/18
3.9K
37

没有更多内容

加载失败,请刷新页面

加载更多

SSH安全加强两步走

从 OpenSSH 6.2 开始已经支持 SSH 多因素认证,本文就来讲讲如何在 OpenSSH 下启用该特性。 OpenSSH 6.2 以后的版本多了一个配置项 AuthenticationMethods。该配置项可以让 OpenSSH 同时指定...

xiangyunyan
31分钟前
4
0
C或C++不是C/C++

http://www.voidcn.com/article/p-mucdruqa-ws.html

shzwork
今天
6
0
OSChina 周六乱弹 —— 如何将梳子卖给和尚

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @for_ :划水五分钟,专注两小时。分享Various Artists的单曲《贝多芬第8号钢琴奏鸣曲悲伤的第三乐章》: 《贝多芬第8号钢琴奏鸣曲悲伤的第三乐...

小小编辑
今天
191
8
ES5

什么是ES5:比普通js运行要求更加严格的模式 为什么:js语言本身有很多广受诟病的缺陷 如何:在当前作用域的顶部添加:"use strict" 要求: 1、禁止给未声明的变量赋值 2、静默失败升级为错误...

wytao1995
今天
7
0
c++ 内联函数调用快的原因

见图片分析

天王盖地虎626
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部