iOS Tips(持续更新)

1. #import@class

  • 除非的确有必要,否则不要引入头文件。一般来说,应该在某个类的头文件中使用向前声明来声明别的类,并在实现文件中引入该类的头文件。这样做可以尽量降低类之间的耦合(coupling)。
  • 有时无法使用向前声明,比如要声明某个类遵循一项协议。这种情况下,尽量把“该类遵循某协议”的这条声明移至“class-continuation分类”中。如果不行的话,就把协议单独放在一个头文件中,然后将其引入。

2. NS_ENUMNS_OPTIONS

Foundation框架定义了两个用于定义枚举类型的宏,NS_ENUMNS_OPTIONS,他们的定义如下:

#define NS_ENUM(_type,_name) \
enum _name : _type _name; enum _name : _type

#define NS_OPTIONS(_type,_name) \
enum _name : _type _name; enum _name : _type

从上面定义可以发现其实这两个宏定义是一致的,区别在于它们的用途,前者主要用于对枚举值没什么特殊要求的枚举类型,而后者经常用于定义可以彼此组合的选项枚举值,如下面例子:

typedef NS_ENUM (NSUInteger, JKOrientation) {
    JKOrientationEast,
    JKOrientationSouth,
    JKOrientationWest,
    JKOrientationNorth
};
typedef NS_OPTIONS (NSUInteger, JKInterfaceOrientation) {
    JKInterfaceOrientationUp    = 1 << 0,
    JKInterfaceOrientationDown  = 1 << 1,
    JKInterfaceOrientationLeft  = 1 << 2,
    JKInterfaceOrientationRight = 1 << 3,
};
  • 应该使用枚举来表示状态机的状态,传递给方法的选项以及状态码等值,给这些值起个易懂的名字。
  • 如果把传递给某个方法的选项表示为枚举类型,而多个选项又可同时使用,那么就将各选项值定义为2的幂,以便按位或操作来将其组合起来。
  • 用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明底层数据类型。这样做可以确保枚举是用开发者所选的底层数据类型实现出来的,而不会采用编译器所选的类型。
  • 在处理枚举类型switch语句中不要实现default分支。这样的话,加入新的枚举之后,编译器就会提示开发者:switch语句并未处理所有枚举。

3. archiveRootObject归档失败

归档的使用简单易懂,是实现预缓存的一种常用方式,我按照如下方式实现预缓存:

+(NSString*)archivePath:(NSString*)archiveName userSpecific:(BOOL)isUserSpecific
{
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    NSString *tmp = nil;

    if (isUserSpecific) {
        NSString *currentUserName = [[NSUserDefaults standardUserDefaults] objectForKey:kKeyForCurrentUserName];
        tmp = [NSString stringWithFormat:@"appCache/%@-%@.archiver",currentUserName,archiveName];
    }else{
        tmp = [NSString stringWithFormat:@"appCache/%@.archiver",archiveName];
    }

    NSString *archivePath = [cachePath stringByAppendingPathComponent:tmp];

    return archivePath;
}

+(NSDictionary*)getCachedDataOf:(NSString*)cacheName userSpecific:(BOOL)isUserSpecific
{
    NSString *archivePath = [JKAppCache archivePath:cacheName userSpecific:isUserSpecific];

    NSDictionary *dic = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];

    return dic;

}

+(void)cacheData:(id)data forPageName:(NSString*)cacheName userSpecific:(BOOL)isUserSpecific;
{
    NSString *archivePath = [JKAppCache archivePath:cacheName userSpecific:isUserSpecific];

    if([NSKeyedArchiver archiveRootObject:data toFile:archivePath]){
        NSLog(@"%@ archive succeed", cacheName);
    }else{
        NSLog(@"%@ archive failed", cacheName);
    }

}

可是天公不作美啊,上述代码总是输出“** archive failed”,然后就用模拟器先调试一把,断点到archiveRootObject,查看获得的archivePath变量,变量打印如下:

/Users/UserName/Library/Developer/CoreSimulator/Devices/BA2F8FD8-D1F8-4DFC-8F1B-E0CADFE635FF/data/Containers/Data/Application/EEEB6664-DB34-4865-AE5B-DF4BFF7BF2EA/Library/Caches/appCache/home.archiver

既然归档失败,那就首先看一下该路径下到底有什么,拷贝该路径,打开Finder,按Shift + CMD + G快捷键,粘贴该路径,“崩”,该路径不存,那…./appCache目录存在吗?也不存在,但是…./Caches目录存在,那么答案粗来了,appCache目录不存在,怎么不存在该目录呢?其实上面代码就未曾建立过该目录,只是简单的在路径中添加了appCache路径而已。既然该目录不存在那就建立该目录,只需要更改获取路径函数,代码如下:

+(NSString*)archivePath:(NSString*)archiveName userSpecific:(BOOL)isUserSpecific
{
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    cachePath = [cachePath stringByAppendingPathComponent:@"appCache"];

    BOOL isDir = NO;
    NSError *error;
    if (! [[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO) {
        [[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:&error];
    }

    NSString *tmp = nil;

    if (isUserSpecific) {
        NSString *currentUserName = [[NSUserDefaults standardUserDefaults] objectForKey:kKeyForCurrentUserName];
        tmp = [NSString stringWithFormat:@"%@-%@.archiver",currentUserName,archiveName];
    }else{
        tmp = [NSString stringWithFormat:@"%@.archiver",archiveName];
    }

    NSString *archivePath = [cachePath stringByAppendingPathComponent:tmp];

    return archivePath;
}

这样就欧了。

你可能感兴趣的:(iOS,Tips)