美文网首页iOS常用
iOS数据存储的五种方式(含FMDB,CoreData使用)

iOS数据存储的五种方式(含FMDB,CoreData使用)

作者: CombatReadiness | 来源:发表于2020-04-17 17:56 被阅读0次

    iOS数据存储通常有以下五种方式:
    1、Plist 2、NSUserDefaults 3、NSkeyedArchiver 4、SQLite 5、CoreData

    等不及想看项目的同学点这儿demo

    1、Plist

    可被序列化的通常有以下几种类型:
    NSString(含NSMutableString),NSArray(含NSMutableArray), NSDictionary(含NSMutableDictionary),NSData(含 NSMutableData),NSNumber,NSDate

    使用方法

    • 不在工程中新建plist文件

    先创建一个plist的存储路径

    NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSString *plistPath = [docuPath stringByAppendingPathComponent:@"hooyking.plist"];
    

    以NSString保存示例

    NSError *error = nil;
    [@"张三" writeToFile:plistPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
    

    NSString数据取出

    NSError *error = nil;
    NSString *string = [NSString stringWithContentsOfFile:plistPath encoding:NSUTF8StringEncoding error:&error];
    
    • 在工程中新建一个plist文件


      plist.png

    以NSArray保存示例

    NSString *customerPlistPath = [[NSBundle mainBundle] pathForResource:@"HK" ofType:@"plist"];
    NSArray *nameArray = @[@"first",@"last"];
    [nameArray writeToFile:customerPlistPath atomically:YES];
    

    NSArray数据取出

    NSArray *customerPlistArray = [NSArray arrayWithContentsOfFile:customerPlistPath];
    NSLog(@"项目中新建的plist文件保存的数据%@",customerPlistArray);
    

    2、NSUserDefaults

    NSUserDefaults支持的数据类型通常有以下几种:
    NSNumber(CGFloat、NSInteger、int、float、double), NSString(含NSMutableString),NSData(含NSMutableData,NSArray(含NSMutableArray),NSDictionary(含NSMutableDictionary),BOOL

    • 基本数据类型
      NSUserDefaults存储的对象全是不可变的,即使存进去的是可变的,取出来也是不可变的,如NSMutableArray存进去,取出来就是NSArray了。

    以NSString保存示例

    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    [ud setObject:self.textField.text forKey:@"userDefaultKey"];
    [ud synchronize];
    

    NSString数据取出

    NSString *text = [ud objectForKey:userDefaultKeyStr];
    NSLog(@"取出的数据%@",text);
    
    • 自定义类型
      使用NSUserDefaults保存自定义类型,自定义类型必须遵循NSCoding协议,下面以PersonModel示例。

    PersonModel.h中遵循<NSCoding>

    PersonModel.h.png
    PersonModel.m中实现解归档
    //归档
    - (void)encodeWithCoder:(NSCoder *)aCoder {
        [aCoder encodeObject:self.name forKey:@"name"];
        [aCoder encodeInteger:self.age forKey:@"age"];
    }
    
    //解档
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
        self = [super init];
        if (self) {
            self.name = [aDecoder decodeObjectForKey:@"name"];
            self.age = [aDecoder decodeIntegerForKey:@"age"];
        }
        return self;
    }
    

    保存数据

    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    PersonModel *model = [PersonModel new];
    model.name = @"张哈哈";
    model.age = 10;
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:model];
    [ud setObject:data forKey:@"customerObjectKey"];
    [ud synchronize];
    

    取出数据

    NSData *data = [ud objectForKey:@"customerObjectKey"];
    PersonModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    NSLog(@"名字:%@--年龄:%zd",model.name,model.age);
    

    3、NSKeyedArchiver

    这里的后缀名用了.data,实际上用什么后缀名都无所谓的。

    • 单个普通数据的归解档

    文件路径

    NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSLog(@"归档文件路径:%@",docuPath);
    NSString *singleCommonFilePath = [docuPath stringByAppendingPathComponent:@"singleCommon.data"];
    

    归档

    NSString *singleString = @"单个普通数据的归档看看如何?";
    BOOL singleSuccess = [NSKeyedArchiver archiveRootObject:singleString toFile:singleCommonFilePath];
    if (singleSuccess) {
        NSLog(@"单个普通数据归档成功");
    } else {
        NSLog(@"单个普通数据归档失败");
    }
    

    解档

    NSString *singleString = [NSKeyedUnarchiver unarchiveObjectWithFile:singleCommonFilePath];
    NSLog(@"单个普通数据的解档:%@",singleString);
    
    • 多个普通数据的归解档

    文件路径

    NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSLog(@"归档文件路径:%@",docuPath);
    NSString *multipleCommonFilePath = [docuPath stringByAppendingPathComponent:@"multipleCommon.data"];
    

    归档

    NSInteger age = 20;
    NSString *name = @"张三";
    NSArray *toies = @[@"柯尼赛格",@"百达斐丽",@"陆家嘴100套房"];
    NSMutableData *mutableData = [[NSMutableData alloc] init];
    NSKeyedArchiver *multipleKeyArchiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mutableData];
    [multipleKeyArchiver encodeInteger:age forKey:@"age"];
    [multipleKeyArchiver encodeObject:name forKey:@"name"];
    [multipleKeyArchiver encodeObject:toies forKey:@"toies"];
    [multipleKeyArchiver finishEncoding];//完成归档
    BOOL multipleSuccess = [mutableData writeToFile:multipleCommonFilePath atomically:YES];//写入文件
    if (multipleSuccess) {
        NSLog(@"多个普通数据归档成功");
    } else {
        NSLog(@"多个普通数据归档失败");
    }
    

    解档

    NSMutableData *mutableData = [NSMutableData dataWithContentsOfFile:multipleCommonFilePath];
    NSKeyedUnarchiver *keyedUnarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:mutableData];
    NSInteger age = [keyedUnarchiver decodeIntegerForKey:@"age"];
    NSString *name = [keyedUnarchiver decodeObjectForKey:@"name"];
    NSArray *toies = [keyedUnarchiver decodeObjectForKey:@"toies"];
    [keyedUnarchiver finishDecoding];
    NSLog(@"多个普通数据的解档:年龄:%zd--名字:%@--玩具:%@,%@,%@",age,name,toies[0],toies[1],toies[2]);
    
    • 自定义对象的归解档

    自定义对象的归档必须遵循NSCoding协议,当然自定义对象还可以包含自定义对象,被包含自定义对象同样需要遵循NSCoding协议,下面以CarModelEngineModel示例,CarModel包含EngineModel

    CarModel.png

    对于自定义对象,不论他是只保存这个对象还是对象的array,dictionary,set,只要此对象遵循了NSCoding协议,都可进行归档

    文件路径

    NSString *docuPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSLog(@"归档文件路径:%@",docuPath);
    NSString *customerModelFilePath = [docuPath stringByAppendingPathComponent:@"car.data"];
    

    归档

    CarModel *car = [[CarModel alloc] init];
    car.price = 50000000;
    car.brand = @"布加迪威龙";
    car.wheelArr = @[@"左前轮",@"右前轮",@"左后轮",@"右后轮"];
    
    EngineModel *engine = [[EngineModel alloc] init];
    engine.model = @"无敌旋风";
    engine.cylinderNumber = 100;
        
    car.engine = engine;
    
    BOOL success = [NSKeyedArchiver archiveRootObject:car toFile:customerModelFilePath];
    if (success) {
        NSLog(@"自定义对象归档成功");
    } else {
        NSLog(@"自定义对象归档失败");
    }
    

    解档

    CarModel *car = [NSKeyedUnarchiver unarchiveObjectWithFile:customerModelFilePath];
    NSLog(@"自定义对象的解档:车价格:%.2f--车标:%@--车轮子:%@,%@,%@,%@--发动机型号:%@--发动机气缸数:%zd",
    car.price,car.brand,car.wheelArr[0],car.wheelArr[1],car.wheelArr[2],car.wheelArr[3],car.engine.model,car.engine.cylinderNumber);
    

    4.SQLite

    SQLite存储类型通常有以下几种:

    NULL NULL值
    REAL 浮点型(如CGFloat,float,double,不过都需要转成NSNumber存)
    INTEGER 整型(如NSInteger,int,不过都需要转成NSNumber存)
    TEXT 文本类(如NSString)
    BLOB 二进制(如图片、文件NSData

    注意这个插入的数据那些都是对象,text对应NSString,blob对应NSData,integer对应NSNumber

    通常我们不直接使用系统的SQLite,而是用FMDB,它是对SQLite的封装,使用更加优美。

    下面就详细说说FMDB的使用

    数据库路径及初始化FMDatabase

    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSLog(@"documentPath:%@",path);
    NSString *dbpath = [path stringByAppendingPathComponent:@"hooyking.db"];
    FMDatabase *db = [FMDatabase databaseWithPath:dbpath];
    self.myDb = db;
    

    对表操作后记得一定要调用close方法

    • 创建表
    - (void)createTable {
        if ([_myDb open]) {
            //这儿创建了一个列有 name|sex|age|nickname|phoneNum|nativePlace|photo 的名字为personTable的表
            BOOL result = [_myDb executeUpdate:@"create table if not exists personTable (name text, sex integer, age integer, nickname text, phoneNum text, nativePlace text, photo blob)"];
            if (result) {
                NSLog(@"创建表成功");
            }
            else {
                NSLog(@"创建表失败");
            }
            [_myDb close];
        }
    }
    
    • 插入数据
    - (void)insertData {
        if ([_myDb open]) {
            BOOL result = [_myDb executeUpdate:@"insert into personTable (name, sex, age, nickname, phoneNum, nativePlace, photo) values (?,?,?,?,?,?,?)",@"JDX",[NSNumber numberWithInteger:1],[NSNumber numberWithInteger:18], @"hooyking", [NSNumber numberWithInteger:13888888888],@"sichuan",[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"picture" ofType:@"jpg"]]];
            if (result) {
                NSLog(@"添加数据成功");
            }
            else {
                NSLog(@"添加数据失败");
            }
            [_myDb close];
        }
    }
    
    • 删除数据
    - (void)deleteData {
        //删除这个表里nickname为hooyking的所有数据,列没有删除,依然存在
        if ([_myDb open]) {
            BOOL result = [_myDb executeUpdate:@"delete from personTable where nickname = ?",@"hooyking"];
            if (result) {
                NSLog(@"删除数据成功");
            }
            else {
                NSLog(@"删除数据失败");
            }
            [_myDb close];
        }
    }
    
    • 修改数据
    - (void)updateData {
        if ([_myDb open]) {
            BOOL result = [_myDb executeUpdate:@"update personTable set age = ? where nickname = ?",[NSNumber numberWithInteger:25],@"hooyking"];
            if (result) {
                NSLog(@"修改数据成功");
            }
            else {
                NSLog(@"修改数据失败");
            }
            [_myDb close];
        }
    }
    
    • 查询数据
    - (void)selectData {
        if ([_myDb open]) {
            //查询多条数据
            FMResultSet *res = [_myDb executeQuery:@"select name, age from personTable"];
            while ([res next]) {
                NSString *name = [res stringForColumn:@"name"];
                NSInteger age = [res intForColumn:@"age"];
                NSLog(@"姓名:%@----年龄:%ld",name,age);
            }
            
            //查询一条数据
            NSLog(@"年龄为25的人:%@",[_myDb stringForQuery:@"select name from personTable where age = ?",@25]);
            
            [_myDb close];
        }
    }
    
    • 建多张表,插入,查询多个数据等
    - (void)moreOperate {
        if ([_myDb open]) {
            //创建表
            NSString *createSql = @"create table if not exists studentsTable1 (id integer, name text, sex integer);"
                                   "create table if not exists studentsTable2 (id integer, name text, sex integer);"
                                   "create table if not exists studentsTable3 (id integer, name text, sex integer);";
            BOOL createResult = [_myDb executeStatements:createSql];
            if (createResult) {
                NSLog(@"创建多张表成功");
            }
            else {
                NSLog(@"创建多张表失败");
            }
            //*********************************插入多条数据(这里涉及到线程安全)**************************************
            
            //**********************方法一*********************
            NSString *insertSql = @"insert into studentsTable1 (id, name, sex) values ('100', '张三', '1');"
                                   "insert into studentsTable2 (id, name, sex) values ('200', '李四', '1');"
                                   "insert into studentsTable3 (id, name, sex) values ('300', '如花', '0');";
            BOOL insertResult = [_myDb executeStatements:insertSql];
            if (insertResult) {
                NSLog(@"插入数据成功");
            }
            else {
                NSLog(@"插入数据失败");
            }
            
            //*********************方法二**********************
            //看这个方法:moreQueue
            
            
            //查询数据
            NSString *selectSql = @"select * from studentsTable1;"
                                   "select * from studentsTable2;"
                                   "select * from studentsTable3;";
            BOOL selectResult = [_myDb executeStatements:selectSql withResultBlock:^int(NSDictionary *dictionary) {
                NSLog(@"moreOperate查询到的结果:%@", [[dictionary allValues] componentsJoinedByString:@","]);
                return 0;
            }];
            if (selectResult) {
                NSLog(@"查询成功");
            }
            else {
                NSLog(@"查询失败");
            }
            [_myDb close];
        }
    }
    
    • 多个数据插入线程安全
    - (void)moreQueue {
        //方法二里面线程安全又有两种方式,ok继续看
        if ([_myDb open]) {
            NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
            NSString *dbpath = [path stringByAppendingPathComponent:@"hooyking.db"];
            FMDatabaseQueue *dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbpath];
            //第一种(一般就用这种就能保证线程安全了,那条数据有错,那么有错那条就不会插入进去,例如id改为i,自己看效果)
            [dbQueue inDatabase:^(FMDatabase *db) {
                [db executeUpdate:@"insert into studentsTable1 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:500], @"王五", [NSNumber numberWithInteger:1]];
                [db executeUpdate:@"insert into studentsTable2 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:600], @"陆六", [NSNumber numberWithInteger:1]];
                [db executeUpdate:@"insert into studentsTable3 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:700], @"史真香", [NSNumber numberWithInteger:0]];
            }];
            //第二种事务(当插入数据有错时,直接取消将插入的数据,可以改下列试试,例如id改为i,自己看效果)
    //        [dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    //            BOOL res1 = [db executeUpdate:@"insert into studentsTable1 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:500], @"王五", [NSNumber numberWithInteger:1]];
    //            BOOL res2 = [db executeUpdate:@"insert into studentsTable2 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:600], @"陆六", [NSNumber numberWithInteger:1]];
    //            BOOL res3 = [db executeUpdate:@"insert into studentsTable3 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:700], @"史真香", [NSNumber numberWithInteger:0]];
    //            if (!res1 || !res2 || !res3) { //我这样写就是三条任何一条有错,这三条就一条都不插入,这个判断条件若是不写,那就会默认哪一条有错,那一条就不会加入,但是其他的正确的会插入
    //                *rollback = YES;
    //            }
    //            [db executeUpdate:@"insert into studentsTable3 (id, name, sex) values (?,?,?)",[NSNumber numberWithInteger:800], @"你真溜", [NSNumber numberWithInteger:0]];
    //        }];
        
            //查询数据
            NSString *selectSql = @"select * from studentsTable1;"
                                   "select * from studentsTable2;"
                                   "select * from studentsTable3;";
            BOOL selectResult = [_myDb executeStatements:selectSql withResultBlock:^int(NSDictionary *dictionary) {
                NSLog(@"moreQueue查询到的结果:%@", [[dictionary allValues] componentsJoinedByString:@","]);
                return 0;
            }];
            if (selectResult) {
                NSLog(@"查询成功");
            }
            else {
                NSLog(@"查询失败");
            }
            
            [_myDb close];
        }
    }
    
    • 对列的操作

    • 添加列

    - (void)addColumn {
        if ([_myDb open]) {
            //这儿添加了添加名字为temp类型为text的列
            BOOL addColumnRes = [_myDb executeUpdate:@"alter table studentsTable1 add temp text"];
            if (addColumnRes) {
                NSLog(@"添加列成功");
            }
            else {
                NSLog(@"添加列失败");
            }
            
            [_myDb close];
        }
    }
    
    • 删除列
      SQLite不支持alter对列进行修改与删除的方法来的,所以要删除列的替代方式为新建一个没有你要删除的列的表
      第一步:create table testTable(id integer, name text, sex integer);创建一个新表testTable,这个表没有列temp了;
      第二步:insert into testTable select id, name, sex from studentsTable1;这儿完成了将表studentsTable1列id name sex中的全部数据插入到了表testTable中;
      第三步:drop table if exists studentsTable1;删除原来的表studentsTable1;
      第四步:alter table testTable rename to studentsTable1;将testTable重命名为studentsTable1,若是你要修改列名,方式和删除一样,可自己操作一下。

    • 删除表

    - (void)dropTable {
        //销毁这张表(即这个表删除后就不存在了)
        if ([_myDb open]) {
            BOOL result = [_myDb executeUpdate:@"drop table if exists personTable"];
            if (result) {
                NSLog(@"销毁表成功");
            }
            else {
                NSLog(@"销毁表失败");
            }
            [_myDb close];
        }
    }
    

    5、CoreData

    新建项目时可勾选Use Core Data,勾选之后创建的项目就自带CoreData了


    勾选Use Core Data.png

    若是不勾选,新建的项目就没有CoreData文件,想使用CoreData就要通过New File选择Data Model

    不勾选Use Core Data.png

    建好之后为如下图所示


    CoreData文件刚建好.png

    点击下方Add Entity添加实体

    这儿我们添加Teacher与Student实体

    Teacher实体添加好后.png Teacher实体设置关联关系后.png Student实体设置关联关系后.png

    右侧Relationship设置

    Properties
    transient:设置当前属性是否只存在于内存,不被持久化到本地,如果设置为YES,关联关系属性就不参与持久化操作。transient设置为YES一般存储一些在内存中缓存的数据,如存储临时数据,当app杀死后数据不会存在本地,该选项默认NO。
    optional: 设置向MOC保存数据时,这个属性是否必须有值。设置为NO时,MOC进行操作时,若是无值,会失败并返回一个error,该选项默认YES。

    Delete Rule
    设置关联属性的删除规则。一共四个值:这儿一般选后三个值,当选No Action时,Xcode也会报警告,让设置一个关联关系。
    No Action:当前实体删除后对关联实体无任何操作,也不会将关联对象的关联属性指向nil,删除后使用关联对象的关联属性,可能会导致其他问题。
    Nullify:删除后会将关联实体的关联属性指向nil,delete Rule默认值。
    Cascade:删除当前对象后,会将与之关联的实体也一并删除。
    Deny:在删除当前实体时,如果当前对象还指向其他关联对象,则当前实体不能被删除。

    Type
    设置当前实体与关联实体的关联关系
    To One:当前实体只可持有1个关联实体(默认值)
    To Many:当前实体只可持有多个关联实体

    Count只有选择To Many时才有
    设置最小值与最大值,默认值不设置
    Minimum:最小值
    Maximum:最大值

    Advanced
    设置索引
    indexed: 设置当前属性是否是索引。添加索引后可以提升检索速度,但是对于删除操作,删除索引后其他地方还需要做出相应的变化,所以速度会比较慢,默认值NO。

    Spotlight
    Store in External Record File: 当存储二进制文件时,如果遇到比较大的文件,是否存储在存储区之外。如果选择YES,存储文件大小超过1MB的文件,都会存储在存储区之外。否则大型文件存储在存储区内,会造成SQLite进行表操作时,效率受到影响,默认值NO。

    设置好关系后创建模型文件
    Xcode->Editor->Create NSManageredObject Subclass 勾选两个实体,创建好后会报错,在如下图里找到文件,移除后就没了

    build Phases删除四个文件.png

    你可以在student属性里看到如此这般
    @property (nullable, nonatomic, retain) NSSet<Teacher *> *teachers;
    你可以在Teacher属性里看到如此这般
    @property (nullable, nonatomic, retain) NSSet<Student *> *students;

    • 创建CoreData数据库
    - (void)createCoreDataLite {
        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreData" withExtension:@"momd"];//CoreData为你自定义的CoreData文件名,momd为固定的类型
        NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
        NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"coreData.sqlite"];
        NSLog(@"数据库地址%@",path);
        NSURL *sqlURL = [NSURL fileURLWithPath:path];
        NSError *error = nil;
        [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqlURL options:nil error:&error];
        if (error) {
            NSLog(@"错误%@",error);
        } else {
            NSLog(@"创建数据库成功,如果已添加此数据库,就算再次调用也不用重复添加,直接使用以前的");
        }
        NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        context.persistentStoreCoordinator = store;
        self.context = context;
    }
    
    • 添加数据
    - (void)insertData {
        Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context];
        student.name = [NSString stringWithFormat:@"Student%d",arc4random()%100];
        student.age = arc4random()%20;
        student.sex = arc4random()%2 == 0 ?  @"女" : @"男";
    
        Teacher *teacher = [NSEntityDescription insertNewObjectForEntityForName:@"Teacher" inManagedObjectContext:self.context];
        teacher.name = [NSString stringWithFormat:@"Teacher%d",arc4random()%100];
        teacher.age = arc4random()%60;
        teacher.students = [NSSet setWithArray:@[student]];
        
        NSError *error = nil;
        if ([self.context save:&error]) {
            NSLog(@"插入成功");
        } else {
            NSLog(@"插入失败");
        }
    }
    
    • 删除数据
    - (void)deleteData {
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Teacher"];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 50"];
        request.predicate = predicate;
        NSArray *deleteArray = [self.context executeFetchRequest:request error:nil];
        for (Teacher *model in deleteArray) {
            NSLog(@"老师的学生%@",model.students);
            [self.context deleteObject:model];
        }
        NSError *error = nil;
        if ([self.context save:&error]) {
            NSLog(@"删除成功");
        } else {
            NSLog(@"删除失败%@",error);
        }
    }
    
    • 更新数据
    - (void)updateData {
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Teacher"];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 45"];
        request.predicate = predicate;
        NSArray *updateArray = [self.context executeFetchRequest:request error:nil];
        for (Teacher *model in updateArray) {
            model.name = @"张三";
        }
        NSError *error = nil;
        if ([self.context save:&error]) {
            NSLog(@"更新成功");
        } else {
            NSLog(@"更新失败");
        }
    }
    
    • 查询数据
    - (void)findData {
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Teacher"];
        //此处可写查询条件(更多条件设定可浏览器自行搜索)
    //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 50"];
    //    request.predicate = predicate;
        //此处可写排序条件(这儿按年龄排序)
    //    NSSortDescriptor *ageSort = [NSSortDescriptor sortDescriptorWithKey:@"age"ascending:YES];
    //    request.sortDescriptors = @[ageSort];
        NSArray *resultArray = [self.context executeFetchRequest:request error:nil];
        self.dataMArray = [resultArray mutableCopy];
        [self.tableView reloadData];
    }
    

    相关文章

      网友评论

        本文标题:iOS数据存储的五种方式(含FMDB,CoreData使用)

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