程序员iOS Developer

iOS轻量数据存储

2016-09-09  本文已影响0人  pppotion

在北京实习的几个月里,第一次接触OC。之前有接触iOS,但码代码不是很多,也只是学校的一个小项目,当时还是swift1.0版本。

这次总结的是iOS的轻量级数据存储,如果说你要给你的app存储一些账号密码,一些设置的开关(true false)之类的很小的数据,以供下次读取,建议使用NSUserDefaults类。

先来看一下苹果的官方解释:
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html

The NSUserDefaults class provides a programmatic interface for interacting with the defaults system. The defaults system allows an application to customize its behavior to match a user’s preferences. For example, you can allow users to determine what units of measurement your application displays or how often documents are automatically saved. Applications record such preferences by assigning values to a set of parameters in a user’s defaults database. The parameters are referred to as defaults since they’re commonly used to determine an application’s default state at startup or the way it acts by default.

At runtime, you use an NSUserDefaults object to read the defaults that your application uses from a user’s defaults database. NSUserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value. The synchronize method, which is automatically invoked at periodic intervals, keeps the in-memory cache in sync with a user’s defaults database.

The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Booleans, and URLs. A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData. For more details, see Preferences and Settings Programming Guide.

简单来说,OC提供这个类让你的app可以以直接赋值的方式将数据存储到用户的默认数据库里。下次要用到你存储的数据时,直接使用NSUserDefaults对象去读就行了。Synchronize这个方法是把缓存和数据库进行同步。NSUserDefaults 能存的数据类型有:floats, doubles, integers, Booleans, and URLs等。记得NSUserDefaults是一个单例,是线程安全的,在整个程序中只有一个实例对象。

一. 缓存普通数据

  1. 存储:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

[userDefaults  setBool: NO forKey:IMAGES_DISPLAY_KEY];

[userDefaults  setFloat: myFlout forKey:MY_FLOAT];

[userDefaults  setObject:listData forKey:BANNER_IMAGE];

记得再赋值后调用synchronize方法,不然数据不会同步到数据库里。


[userDefaults synchronize];

存储方法除了这三种还有:setInteger:forKey、setDouble:forKey、setURL:forKey 。大家选择相应的方法使用。

2.读取:


NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

_imageDisplayOrNotSwitch.on = [_userDefaults boolForKey:IMAGES_DISPLAY_KEY];

_myFlout = [_userDefaults floatForKey:MY_FLOAT];

NSData* listData = [[NSUserDefaults standardUserDefaults] objectForKey:BANNER_IMAGE];

这样就方便地完成读取了。值得一提的是 IMAGES_DISPLAY_KEY,MY_FLOAT,BANNER_IMAGE这三个key我都存在了另一个文件里,LocalDataKey.h。所以记得import LocalDataKey.h。

LocalDataKey.h 里是这样的


#ifndef LocalDataKey_h

#define LocalDataKey_h

#define BANNER_IMAGE @"BannerImage"

#define IMAGES_DISPLAY_KEY @"ImageDisplayKey"

#define MY_FLOAT @"MyFloat"

如果有其他的想存储的数据,也可以将key存在这个里面,简单方便。值得注意的是要保证每个key的唯一性,不能有重复,不然会出现数据混淆或错误。

还有一点值得说明的是,NSUserDefaults存储的值是immutable的,是不可变的。比如你要存储一个NSMutableArray的array,你需要重新建立一个array:


NSArray * array = [NSArray arrayWithArray:mutableArray];

再将array使用 [user setObject:array forKey:@"blablabla"]; 存数据,别忘了使用synchronise方法同步到数据库。

二. 缓存自定义对象

实际上NSUserDefaults不支持存储自定义对象, 但支持存储NSData,举个我实习时的例子:

BBBanner.h


#import@interface BBBanner : NSObject

@property (retain,nonatomic) NSString *title;

@property (retain,nonatomic) NSString *href;

@property (retain,nonatomic) NSNumber *type;

@property (retain,nonatomic) NSString *src;

@end

很多人看到这里会想不到下一步会做什么,我们需要做的是将BBBanner这个类型变成NSData。这一步叫归档。首先在.h 文件中申明 NSCoding 协议,再 在 .m 中实现 encodeWithCoder 方法和initWithCoder 方法。实现如下:

BBBanner.m:


#import "BBBanner.h"

#define kType @"BannerTypeKey"

#define kSrc @"BannerSrcKey"

#define kTitle @"BannerTitleKey"

#define kHref @"BannerHrefKey"



@implementation BBBanner

- (void)encodeWithCoder:(NSCoder *)aCoder

{

[aCoder encodeObject:_type forKey:kType];

[aCoder encodeObject:_src forKey:kSrc];

[aCoder encodeObject:_title forKey:kTitle];

[aCoder encodeObject:_href forKey:kHref];

}

- (id) initWithCoder:(NSCoder *)aDecoder

{

self = [[BBBanner alloc] init];

self.type = [aDecoder decodeObjectForKey:kType];

self.href = [aDecoder decodeObjectForKey:kHref];

self.title = [aDecoder decodeObjectForKey:kTitle];

self.src = [aDecoder decodeObjectForKey:kSrc];

return self;

}

@end

这样就将BBBanner这个类型转换成NSData了。

接下来我们实现存储:


BBBanner* banner = [[BBBanner alloc] init];

banner.title = @"hi title";

banner.href = @"hi href";

banner.type = 1;

banner.src = @"www.google.com";



//使用archivedDataWithRootObject转换类型

NSData *bannerData = [NSKeyedArchiver archivedDataWithRootObject: banner];

[bannerDataArray addObject:bannerData];

[_userDefaults setObject:bannerData forKey:BANNER_DATA];

[_userDefaults synchronize];

这样就成功的把banner的类型存进NSUserDefaults啦。同样也可以转换一个里面全是banner类型的NSMutableArray。比如:


NSArray* bannerModels = [BBBanner mj_objectArrayWithKeyValuesArray: dic]; //dic是从网络上请求过来的NSDictionary,mj_objectArrayWithKeyValuesArray是一个引用的库里的方法,可以将一个array里的object类型通过dic转换成BBBanner或者是任意一个你自己创建的类型,像上面一样记得归档。 

NSData *listData = [NSKeyedArchiver archivedDataWithRootObject: bannerModels];

实现读取:

NSData* bannerData = [[NSUserDefaults standardUserDefaults] objectForKey:BANNER_DATA];

//使用unarchiveObjectWithData将数据类型转换回去
BBBanner* banner = [NSKeyedUnarchiver unarchiveObjectWithData:bannerData];

过些时间我会考虑加上存储整个包含自定义类型的数组的实现方法,其实大同小异。

三. 有些人会问 存储的数据到底去哪里了?

这个我也是上网搜了其他的文章才大概有点了解。

它存储在应用程序内置的一个plist文件里,这个可以根据路径看到。详见 http://blog.csdn.net/enuola/article/details/7959767

四.其他的有可能用到的方法

containsObject方法。贴上一段小代码:

if([_userDefaults.dictionaryRepresentation.allKeys containsObject:PUSH_NOTIFICATION_KEY])

{

_pushNotifSwitch.on = [_userDefaults boolForKey:PUSH_NOTIFICATION_KEY];

}

else

{

_pushNotifSwitch.on = YES;

}

这个方法是查找是否有无你需要的key,如果没有,你就有可能读取到NULL,然后导致程序crash之类的。还是挺值得注意的一个方法。

大概要说的就这么多。如果有指正,请随意回复。

上一篇下一篇

猜你喜欢

热点阅读