• iOS中几种数据持久化方案


    概念

    所谓持久化就是将数据保存到硬盘中,使得应用重启或者机器重启后可以继续访问之前保存的数据。

    方案

    • plist文件(属性列表)
      将某些特定的类,通过XML文件的方式保存在目录中。

      1. 获得文件路径

         NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
         NSString *fileName = [path stringByAppendingPathComponent:@"myplist.plist"];
        
      2. 存储

         NSArray *array = @[@"123", @"456", @"789"];
         [array writeToFile:fileName atomically:YES];
        
      3. 读取

         NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
         NSLog(@"%@", result);
        
    • preference(偏好设置)

      1. 获得NSUserDefaults文件

         NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        
      2. 向文件中写入内容

         [userDefaults setObject:@"myString" forKey:@"string"];
         [userDefaults setBool:YES forKey:@"bool"];
         [userDefaults setInteger:21 forKey:@"integer"];
        
      3. 立即同步

         [userDefaults synchronize];
        
      4. 读取文件

         NSString *name = [userDefaults objectForKey:@"string"];
         BOOL sex = [userDefaults boolForKey:@"bool"];
         NSInteger age = [userDefaults integerForKey:@"integer"];
        
    • NSKeyedArchiver(归档)

      1. 属性设置

         @interface Person : NSObject //2.设置属性
         @property (strong, nonatomic) UIImage *avatar;
         @property (copy, nonatomic) NSString *name;
         @property (assign, nonatomic) NSInteger age;
         @end
        

      2.实现协议方法

      NSCoding协议声明了两个方法,这两个方法都是必须实现的。一个用来说明如何将对象编码到归档中,另一个说明如何进行解档来获取一个新对象。

        //解档
        - (id)initWithCoder:(NSCoder *)aDecoder {
        	if ([super init]) {
        	self.avatar = [aDecoder decodeObjectForKey:@"avatar"];
        	self.name = [aDecoder decodeObjectForKey:@"name"];
        	self.age = [aDecoder decodeIntegerForKey:@"age"];
        	}
        	return self;
        }
        //归档
        - (void)encodeWithCoder:(NSCoder *)aCoder {
        	[aCoder encodeObject:self.avatar forKey:@"avatar"];
        	[aCoder encodeObject:self.name forKey:@"name"];
        	[aCoder encodeInteger:self.age forKey:@"age"];
        }
      

      如果需要归档的类是某个自定义类的子类时,就需要在归档和解档之前先实现父类的归档和解档方法。即 [super encodeWithCoder:aCoder] 和 [super initWithCoder:aDecoder] 方法;

      3.使用

      需要把对象归档是调用NSKeyedArchiver的工厂方法 archiveRootObject: toFile: 方法。

        NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
        Person *person = [[Person alloc] init];
        person.avatar = self.avatarView.image;
        person.name = self.nameField.text;
        person.age = [self.ageField.text integerValue];
        [NSKeyedArchiver archiveRootObject:person toFile:file];
      

      需要从文件中解档对象就调用NSKeyedUnarchiver的一个工厂方法 unarchiveObjectWithFile: 即可。

        NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
        Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
        if (person) {
        	self.avatarView.image = person.avatar;
        	self.nameField.text = person.name;
        	self.ageField.text = [NSString stringWithFormat:@"%ld", person.age];
        }
      
    • SQLite3
      SQLite3的使用还是比较麻烦,在一般开发过程中,使用的都是第三方开源库 FMDB

      1. 打开数据库

         NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.db"];
         FMDatabase *database = [FMDatabase databaseWithPath:path];
         if (![database open]) {
         NSLog(@"数据库打开失败!");
         }
        
      2. 更新

         //常用方法有以下3种:
         - (BOOL)executeUpdate:(NSString*)sql, ...
         - (BOOL)executeUpdateWithFormat:(NSString*)format, ...
         - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
         //示例
         [database executeUpdate:@"CREATE TABLE IF NOT EXISTS t_person(id integer primary key autoincrement, name text, age integer)"];
         //或者
         [database executeUpdate:@"INSERT INTO t_person(name, age) VALUES(?, ?)", @"Bourne", [NSNumber numberWithInt:42]];
        
      3. 查询

         查询方法有3种
         - (FMResultSet *)executeQuery:(NSString*)sql, ...
         - (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
         - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
         查询示例
         //1.执行查询
         FMResultSet *result = [database executeQuery:@"SELECT * FROM t_person"];
         //2.遍历结果集
         while ([result next]) {
         	NSString *name = [result stringForColumn:@"name"];
         	int age = [result intForColumn:@"age"];
         }
        
      4. 线程安全

        • 创建队列

            FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
          
        • 使用队列

            [queue inDatabase:^(FMDatabase *database) {
            	[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_1", [NSNumber numberWithInt:1]];
            	[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_2", [NSNumber numberWithInt:2]];
            	[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_3", [NSNumber numberWithInt:3]];
            	FMResultSet *result = [database executeQuery:@"select * from t_person"];
            	while([result next]) {
            	}
            }];
          
    • CoreData

      1. 创建项目的时候选择使用Core Data,项目创建成功后,会在AppDelegate类中自动添加相关代码,此外,还会自动生成一个数据模型文件。如果项目在创建的时候没有选择使用Core Data,但是在后面需要使用,那么需要手动的添加AppDelegate中的相关代码。此外还需要手动添加一个Data Model文件。
        在创建Data Model文件时需要注意文件名要与AppDelegate.m中managedObjectModel方法中提到的文件名称相匹配。

      2. 有了Data Model文件后,就可以在里面添加实体和关系,实际上就是向数据库中添加表格和建立表格之间的关联。

      3. 创建好实体后,可以通过添加NSManagedObject subclass文件,系统可以自动添加实体对应的数据模型类。

      4. 通过代码实现数据库的操作

        • 插入数据

            -(void)insert {       
             AppDelegate *delegate = [[UIApplication sharedApplication] delegate];        
            //1. 获得context    
            NSManagedObjectContext *context = delegate.managedObjectContext;    
            //2. 找到实体结构,并生成一个实体对象   
             /*     NSEntityDescription实体描述,也就是表的结构     参数1:表名字     参数2:实例化的对象由谁来管理,就是context     */   
              NSManagedObject *stu = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:context];  
              NSManagedObject *class1 = [NSEntityDescription insertNewObjectForEntityForName:@"Classes" inManagedObjectContext:context];    
              [class1 setValue:[NSNumber numberWithInt:1] forKey:@"c_id"];    
              [class1 setValue:@"一班" forKey:@"c_name"];        
              //3. 设置实体属性值    
              [stu setValue:[NSNumber numberWithInt:1] forKey:@"s_id"];    
              [stu setValue:@"jerehedu" forKey:@"s_name"];    
              [stu setValue:class1 forKey:@"s_class"];        
              //4. 调用context,保存实体,如果没有成功,返回错误信息    
              NSError *error;    
              if ([context save:&error]){        
              	NSLog(@"save ok");    
              } else{        
              	NSLog(@"%@",error);   
              }}
          
        • 查询全部数据

            -(void)selectAll {    
            AppDelegate *delegate = [[UIApplication sharedApplication] delegate]; 
            NSManagedObjectContext *context = delegate.managedObjectContext;        
            NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];        
            //构造查询对象    
            NSFetchRequest *request = [[NSFetchRequest alloc] init];    
            [request setEntity:stu];        
            //执行查询,返回结果集    
            NSArray *resultAry = [context executeFetchRequest:request error:nil];        
            //遍历结果集    
            for (NSManagedObject *enity in resultAry) {        
            	NSLog(@"id=%i name=%@ class=%@",[[enity valueForKey:@"s_id"] intValue],[enity valueForKey:@"s_name"],[[enity valueForKey:@"s_class"] valueForKey:@"c_name"]);    
            }}
          
        • 查询指定数据

            - (void)selectAll {    
            		AppDelegate *delegate = [[UIApplication sharedApplication] delegate];        
            		NSManagedObjectContext *context = delegate.managedObjectContext;        
            		NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];        
            		//构造查询对象    
            		NSFetchRequest *request = [[NSFetchRequest alloc] init];    
            		[request setEntity:stu];        
            		//执行查询,返回结果集    
            		NSArray *resultAry = [context executeFetchRequest:request error:nil];        
            		//遍历结果集    
            		for (NSManagedObject *enity in resultAry) {        
            			NSLog(@"id=%i name=%@ class=%@",[[enity valueForKey:@"s_id"] intValue],[enity valueForKey:@"s_name"],[[enity valueForKey:@"s_class"] valueForKey:@"c_name"]);    
            		}}
          
        • 删除指定数据

            - (void)delete{    
            	//删除 先找到,然后删除    
            	AppDelegate *delegate = [[UIApplication sharedApplication] delegate];    
            	NSManagedObjectContext *context = delegate.managedObjectContext;        
            	NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];        
            	NSFetchRequest *request = [NSFetchRequest new];    
            	[request setEntity:stu];        
            	//构造查询条件,相当于where子句    
            	NSPredicate *predicate = [NSPredicate predicateWithFormat:@"s_id=%i",1];        
            	//把查询条件放进去    
            	[request setPredicate:predicate];    
            	//执行查询    
            	NSManagedObject *obj = [[context executeFetchRequest:request error:nil] lastObject];    
            	//删除    
            	if (obj) {        
            		[context deleteObject:obj];        [context save:nil];    
            		}        
            		[self selectAll];
            		}
  • 相关阅读:
    如何让 PADS Layout 识别到板框
    笔记:理想和挣钱
    笔记:知数据不知情况
    关于ie6下拖动滚动条时,div抖动的问题解决
    jQuery 中屏蔽浏览器的F5刷新功能
    jQuery 的append在ie下的兼容性
    协程
    进程
    操作系统的发展史
    python_控制台输出带颜色的文字方法
  • 原文地址:https://www.cnblogs.com/AliliWl/p/6108528.html
Copyright © 2020-2023  润新知