iOS客户端开发数据存储使用总结

作者: kmplayer | 来源:发表于2017-07-10 14:21 被阅读59次

    数据存储是程序开发中必然会遇到的一个技术需求。真是因为需求的普遍,对应的相关也琳琅满目,令人眼花缭乱。以iOS客户端开发为例,光是系统提供的数据持续化存储的技术就有归档、keychain、NSUserDefault、plist文件等,加上常规的文档读写、数据库、xml等。如何根据项目的实际需要,选择合适的存储技术,值得我们深思。
    本文以Firefly_iOS为例,对使用的相关存储技术和选型理由进行了总结。

    正文

    Firefly_iOS中,使用的数据存储主要涉及到下面几类:

    • 1,keychain
    • 2,数据库
    • 3,NSUserDefault
    一、keychain

    使用场景
    iOS设备中的Keychain是一个安全的存储容器,可以用来为不同应用保存敏感信息比如用户名,密码,网络密码,认证令牌。苹果自己用keychain来保存Wi-Fi网络密码,VPN凭证等等。它是一个在所有app之外的sqlite数据库。
    如果我们手动把自己的私密信息加密,然后通过写文件保存在本地,再从本地取出不仅麻烦,而且私密信息也会随着App的删除而丢失。iOS的Keychain能完美的解决这些问题。并且从iOS 3.0开始,Keychain还支持跨程序分享。这样就极大的方便了用户。省去了很多要记忆密码的烦恼。
    基于上述keychain实现的定位,只有那些比较敏感的数据,并且应用被卸载重装后还希望保留的敏感数据,我们才会选择存放到keychain。例如,用户设置手势密码,需要和应用标识绑定,这个应用标识存放在keychain,就非常合适。

    使用介绍
    Firefly_iOS对于keychain的使用,是基于三方库SAMKeychain的封装。
    具体的对外暴露接口如下:

    @interface FireflyKeychain : NSObject
    
    /**
     *  返回指定服务和用户名的密码值,返回格式为NSString
     *
     *  @param serviceName 服务名
     *  @param aName       用户名
     *
     *  @return 指定服务名和用户名的密码,不存在返回nil
     */
    + (NSString *)passwordForService:(NSString *)serviceName username:(NSString *)aName;
    
    /**
     *  返回指定服务和用户名的密码值,返回格式为NSData
     *
     *  @param serviceName 服务名
     *  @param aName       用户名
     *
     *  @return 指定服务名和用户名的密码,不存在返回nil
     */
    + (NSData *)passwordDataForService:(NSString *)serviceName username:(NSString *)aName;
    
    /**
     *  keychain中设置密码
     *
     *  @param password    密码,格式为NSString
     *  @param serviceName 服务名
     *  @param aName       用户名
     *
     *  @return 成功YES,否则NO
     */
    + (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName username:(NSString *)aName;
    
    /**
     *  keychain中设置密码
     *
     *  @param password    密码,格式为NSData
     *  @param serviceName 服务名
     *  @param aName       用户名
     *
     *  @return 成功YES,否则NO
     */
    + (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName username:(NSString *)aName;
    
    /**
     *  删除keychain中的密码
     *
     *  @param serviceName 服务名
     *  @param aName    用户名
     *
     *  @return 成功YES,否则NO
     */
    + (BOOL)deletePasswordForService:(NSString *)serviceName username:(NSString *)aName;
    
    @end
    
    二、数据库

    使用场景
    iOS客户端数据库的使用场景主要用于缓存数据较大的数据。比如,一些下发的网络json数据。

    使用介绍
    iOS客户端的数据库基本都是使用系统自带的sqlite数据库。目前使用较多的是fmdb。尽管fmdb已经对于底层sqlite作了一层封装,但是对于一般的客户端应用,fmdb还是显得有点大了。
    开源库YTKKeyValueStore基于fmdb作了进一步的封装,对于常规的数据库存储完全够用了。因此,Firefly_iOS目前也主要以YTKKeyValueStore作为数据库使用的底层组件。
    主要的暴露接口如下:

    @interface YTKKeyValueItem : NSObject
    
    @property (strong, nonatomic) NSString *itemId;
    @property (strong, nonatomic) id itemObject;
    @property (strong, nonatomic) NSDate *createdTime;
    
    @end
    
    @interface YTKKeyValueStore : NSObject
    
    - (id)initDBWithName:(NSString *)dbName;
    - (id)initWithDBWithPath:(NSString *)dbPath;
    - (void)createTableWithName:(NSString *)tableName;
    - (BOOL)isTableExists:(NSString *)tableName;
    - (void)clearTable:(NSString *)tableName;
    - (void)dropTable:(NSString *)tableName;
    - (void)close;
    
    ///************************ Put&Get methods *****************************************
    
    - (void)putObject:(id)object withId:(NSString *)objectId intoTable:(NSString *)tableName;
    
    - (id)getObjectById:(NSString *)objectId fromTable:(NSString *)tableName;
    
    - (YTKKeyValueItem *)getYTKKeyValueItemById:(NSString *)objectId fromTable:(NSString *)tableName;
    
    - (void)putString:(NSString *)string withId:(NSString *)stringId intoTable:(NSString *)tableName;
    
    - (NSString *)getStringById:(NSString *)stringId fromTable:(NSString *)tableName;
    
    - (void)putNumber:(NSNumber *)number withId:(NSString *)numberId intoTable:(NSString *)tableName;
    
    - (NSNumber *)getNumberById:(NSString *)numberId fromTable:(NSString *)tableName;
    
    - (NSArray *)getAllItemsFromTable:(NSString *)tableName;
    
    - (NSUInteger)getCountFromTable:(NSString *)tableName;
    
    - (void)deleteObjectById:(NSString *)objectId fromTable:(NSString *)tableName;
    
    - (void)deleteObjectsByIdArray:(NSArray *)objectIdArray fromTable:(NSString *)tableName;
    
    - (void)deleteObjectsByIdPrefix:(NSString *)objectIdPrefix fromTable:(NSString *)tableName;
    
    @end
    
    三、NSUserDefault

    使用场景
    NSUserDefaults适合存储轻量级的本地数据,一些简单的数据(NSString类型的)例如密码,网址等,NSUserDefaults肯定是首选。
    NSUserDefaults是一个单例,在整个程序中只有一个实例对象,他可以用于数据的永久保存,而且简单实用,这是它可以让数据自由传递的一个前提,也是大家喜欢用它保存简单数据的一个主要原因。
    NSUserDefaults支持的数据类型有:NSNumber(NSInteger、float、double),NSString,NSDate,NSArray,NSDictionary,BOOL。

    使用介绍
    如果想要将上述数据类型的数据永久保存到NSUserDefaults中去,只需要简单的操作(一个Value 一个Key ),例如,想要保存一个NSString的对象,代码实现为:

        //将NSString 对象存储到 NSUserDefaults 中
        NSString *passWord = @"1234567";
        NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
        [user setObject:passWord forKey:@"userPassWord"];
    

    将数据取出也很简单,只需要取出key 对应的值就好了,代码如下:

        NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
        NSString *passWord = [ user objectForKey:@"userPassWord"];
    

    Firefly_iOS为了防止以后iOS系统升级可能导致的接口变化,基于系统API作了一层封装,具体的接口如下:

    #import <Foundation/Foundation.h>
    
    @interface FireflyUserDefaultsManager : NSObject
    
    /**
     将数据保存到userDefault数据库
    
     @param value value
     @param key key
     */
    + (void)saveUserDefaultsData:(id )value forKey:(NSString *)key;
    
    /**
     根据 key 来获取对应的值
    
     @param key key
     @return value
     */
    + (id)loadUserDefaultDataByKey:(NSString *)key;
    
    /**
     从userDefault删除key - value
    
     @param key key
     */
    + (void)deleteUserDefaultDataByKey:(NSString *)key;
    
    @end
    
    总结

    从个人开发经验来看,上述的几个方法已经可以满足iOS客户端数据持久化的大部分使用场景。为了便于数据的维护性和迁移性,个人不是十分推荐使用plist、xml等文本方式。当然,具体的场景还是要具体看的。

    参考:
    http://www.cnblogs.com/Jenaral/p/5663096.html
    https://my.oschina.net/u/1245365/blog/294449

    相关文章

      网友评论

        本文标题:iOS客户端开发数据存储使用总结

        本文链接:https://www.haomeiwen.com/subject/oknlhxtx.html