存储一少量数据的存储

所有的应用必然要包括数据的输入输出、存储等技术。iOS开发也不例外。就iOS而言持久化的手段包括:
对于少量数据有NSUserDefaults、写入相关文件file、归解档archive 、keyChain等技术。
对于大量数据就需要用到SQLite数据库,iOS中内置SQLite数据库提供的是C风格的API,一般都用FMDB来操作数据库。iOS还提供了CoreData,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。另外还有就是Realm,Realm也是对象-关系映射(ORM),它有一套自己的数据库存储引擎,比sqlite更轻量级,拥有更快的速度,并且具有很多现代数据库的特性,比如支持JSON,流式api,数据变更通知,自动数据同步,简单身份验证,访问控制,事件处理,最重要的是跨平台,目前已有Java,Objective C,Swift,js,.NET等实现。

沙盒

为了提供更加安全机制,iOS提供了应用程序沙盒机制,保证每个应用程序只能访问本沙盒内的数据。打开模拟器中程序的相应文件夹,可以看到以下文件结构:

  • Documents:除了基于NSUserDefaults的首选设置以外,应用程序的数据、文件都保存在改目录下。
  • Library:基于NSUserDefaults的首选参数保存在Library/Preferences目录下。
  • tmp:该目录供应用程序存储临时文件。

获取Documents目录

NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *document = [pathArr objectAtIndex:0];

获取tmp目录

NSString *tmpPath = NSTemporaryDirectory();

NSUserDefaults保存与读取数据

//保存
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@{@"name":@"diyinqianchang",@"age":@"18"} forKey:@"save"];
[defaults synchronize];

//读取
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id info = [defaults objectForKey:@"save"];
if (info) {
      NSLog(@"%@",info);
}

writeToFiled方法

存储一少量数据的存储_第1张图片
image.png
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *document = [pathArr objectAtIndex:0];
NSString *path = [NSString stringWithFormat:@"%@/myList.plist",document];
NSArray *dataArr = [NSArray arrayWithObjects:@"name",@"age", nil];
[dataArr writeToFile:path atomically:YES];

其他的类似

对象归档保存自定义的类

使用NSKeyedArchiver和NSKeyedUnarchiver进行归解档非常简单。归解档自定义对象,需要此对象遵守NSCoding协议。

.h
#import 
NS_ASSUME_NONNULL_BEGIN
@interface Person : NSObject
@property(nonatomic,strong)NSString *name;
@property(nonatomic,assign)NSInteger age;
-(instancetype)initWithName:(NSString *)name age:(NSInteger)age;
@end
NS_ASSUME_NONNULL_END

.m

#import "Person.h"
@implementation Person
-(instancetype)initWithName:(NSString *)name age:(NSInteger)age
{
    self = [super init];
    if (self) {
        _name = name;
        _age = age;
    }
    return self;
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    _name = [aDecoder decodeObjectForKey:@"name"];
    _age = [aDecoder decodeIntegerForKey:@"age"];
    return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
}
@end
//归档
Person *person = [[Person alloc] initWithName:@"diyinqianchang" age:18];
[NSKeyedArchiver archiveRootObject:person toFile:@"person.archive"];
//解档
Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:@"person.archive"];

注意对象嵌套对象的情况。

钥匙串存储

存储一少量数据的存储_第2张图片
钥匙串

保存在Keychain中的信息即使当应用从设备山卸载后也不会消失,Keychain信息甚至可以在同一开发者的多个应用间共享。Keychain内部可以保存很多的信息。每条信息作为一个单独的keychain item,每个item包含一个data和多个可见的属性。这些属性用来描述data访问、搜索等属性。

存储一少量数据的存储_第3张图片
keychain item
  • SecItemAdd 添加一个keychain item
  • SecItemUpdate 修改一个keychain item
  • SecItemCopyMatching 搜索一个keychain item
  • SecItemDelete 删除一个keychain item
-(NSMutableDictionary *)getKeychainQuery:(NSString *)service
{
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (id)kSecClassGenericPassword, (id)kSecClass,
            service, (id)kSecAttrService,
            service, (id)kSecAttrAccount,
            (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccessible,nil];
}
- (BOOL)createKeychainValue:(NSString *)psd forIdentifier:(NSString *)service {
    NSMutableDictionary *dictionary = [self getKeychainQuery: service];    
//非常值得注意的事kSecValueData字段只接受UTF8格式的 NSData *类型,否则addItem/updateItem就会crash,并且一定记得带上service和account字段
    NSData *psdData = [psd dataUsingEncoding:NSUTF8StringEncoding];
   [dictionary setObject:passwordData forKey:(id)kSecValueData];
   OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);
    if (status == errSecSuccess) {
        return YES;
    }
    return NO;
}
- (void)deleteKeychainValue:(NSString *)service {
    NSMutableDictionary *dictionary = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)dictionary);
}
- (NSData *)searchKeychainCopyMatching:(NSString *)service {
    
    NSMutableDictionary *searchDictionary = [self getKeychainQuery:service];
    //只返回搜索到的第一条item,这个是搜索条件。
    [searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    //返回item的kSecValueData 字段。也就是我们一般用于存放的密码,返回类型为NSData *类型
    [searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
  //我来解释下这里匹配出的是 找到一条符合ksecAttrAccount、类型为普通密码类型kSecClass,返回ksecValueData字段。
    NSData *result = nil;
    OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchDictionary,
                                          (CFTypeRef *)&result);
    [searchDictionary release];
    return result;
}
- (BOOL)updateKeychainValue:(NSString *)password forIdentifier:(NSString *)service {

    NSMutableDictionary *searchDictionary = [self getKeychainQuery:service];
    NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
    NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
    [updateDictionary setObject:passwordData forKey:(id)kSecValueData];
    OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,
                                    (CFDictionaryRef)updateDictionary);    
    if (status == errSecSuccess) {
        return YES;
    }
    return NO;
}

你可能感兴趣的:(存储一少量数据的存储)