您的位置:首页 > 移动开发 > IOS开发

iOS Tips(持续更新)

2015-08-12 22:47 411 查看

1.
#import
@class

除非的确有必要,否则不要引入头文件。一般来说,应该在某个类的头文件中使用向前声明来声明别的类,并在实现文件中引入该类的头文件。这样做可以尽量降低类之间的耦合(coupling)。

有时无法使用向前声明,比如要声明某个类遵循一项协议。这种情况下,尽量把“该类遵循某协议”的这条声明移至“class-continuation分类”中。如果不行的话,就把协议单独放在一个头文件中,然后将其引入。

2.
NS_ENUM
NS_OPTIONS

Foundation框架定义了两个用于定义枚举类型的宏,
NS_ENUM
NS_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;
}


这样就欧了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息