CoreData 条件增删改查,排序,分页

时间:2022-05-25 11:22:52

NSSortDescriptor用于排序


NSPredicate用于查询和过滤

在SQL中作为查询条件通常用WHERE,但在CoreData中作为查询条件就可以用到NSPredicate.

NSPredicate 不单可以和CoreData中的FetchRequest 配合使用。也可以与NSArray配合使用


NSPredicate 中支持的关键词和条件符:

1、>,<,>=,<=,= 比较运算符。

如:

     NSPredicate * qcondition= [NSPredicate predicateWithFormat:@"salary >= 10000"];

2、字符串操作(包含):BEGINSWITH、ENDSWITH、CONTAINS

如:

        @"employee.name BEGINSWITH[cd] '李'" //姓李的员工

     @"employee.name ENDSWITH[c] '梦'"   //以梦结束的员工

     @"employee.name CONTAINS[d] '宗'"   //包含有"宗"字的员工

注:[c]不区分大小写[d]不区分发音符号即没有重音符号[cd]既不区分大小写,也不区分发音符号。

 

3、范围:IN   ,BWTEEN

如:

    @"salary BWTEEN {5000,10000}"

    @"em_dept IN '开发'"

 

4、自身:SELF,这个只针对字符数组起作用。

如:

     NSArray * test = =[NSArray arrayWithObjects: @"guangzhou", @"beijing", @"shanghai", nil];

     @"SELF='beijing'"

 

5、通配符:LIKE

     LIKE 使用?表示一个字符,*表示多个字符,也可以与c、d 连用。

如:

     @"car.name LIKE '?he?'" //四个字符中,中间为he

     @"car.name LIKE '*jp'"   //以jp结束

 

6、正则表达式:MATCHES

如:

NSString *regex = @"^E.+e$";//以E 开头,以e 结尾的字符。
NSPredicate *pre= [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
if([pre evaluateWithObject: @"Employee"]){
NSLog(@"matches YES");

}else{
NSLog(@"matches NO");

}

 

7、逻辑运算符:AND、OR、NOT
如:

      @"employee.name = 'john' AND employee.age = 28"

 

8、占位符:
NSPredicate *preTemplate = [NSPredicate predicateWithFormat:@"name==$NAME"];
NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys:
@"Name1", @"NAME",nil];
NSPredicate *pre=[preTemplate predicateWithSubstitutionVariables: dic];
占位符就是字典对象里的key,因此你可以有多个占位符,只要key 不一样就可以了。



/**

 新增个人记录

 */

- (void)addPerson

{

    /**

     回顾SQL新增记录的过程

     

     1. 拼接一个INSERTSQL语句

     2. 执行SQL

     */

    // 1. 实例化并让context“准备将一条个人记录增加到数据库

    Person *p = [NSEntityDescription insertNewObjectForEntityForName:@"Person"inManagedObjectContext:_context];

    

    // 2. 设置个人信息

    p.name = @"张老头";

    p.age = @10;

    p.phoneNo = @"100";

    p.image = UIImagePNGRepresentation([UIImage imageNamed:@"头像1"]);

    

    // 3. 新增书,实例化并通知上下文准备加书

    Book *b = [NSEntityDescription insertNewObjectForEntityForName:@"Book"inManagedObjectContext:_context];

    b.name = @"太极真经";

    b.price = @20000.99;

    b.author = @"太极忽悠";

    

    Book *b2 = [NSEntityDescription insertNewObjectForEntityForName:@"Book"inManagedObjectContext:_context];

    b2.name = @"一阳神功";

    b2.price = @0.99;

    b2.author = @"老忽悠";


    NSSet *bookSet = [NSSet setWithObjects:b, b2, nil];

    p.books = bookSet;

    

    // 3. 保存(context保存当前的修改)

    if ([_context save:nil]) {

        NSLog(@"新增成功");

    } else {

        NSLog(@"新增失败");

    }

}


/**

 *  删除记录

 */

- (void)removePerson

{

    // 1. 实例化查询请求

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];

    

    // 2. 设置谓词条件

    request.predicate = [NSPredicate predicateWithFormat:@"name = '张老头'"];

    

    // 3. 由上下文查询数据

    NSArray *result = [_context executeFetchRequest:request error:nil];

    

    // 4. 输出结果

    for (Person *person in result) {

        NSLog(@"%@ %@ %@", person.name, person.age, person.phoneNo);

        

        // 删除一条记录

        [_context deleteObject:person];

        break;

    }

    

    // 5. 通知_context保存数据

    if ([_context save:nil]) {

        NSLog(@"删除成功");

    } else {

        NSLog(@"删除失败");

    }

}


/**

 *  更新数据

 *

 *  在常规开发中,应该首先加载所有的数据,帮顶到UITableView中,该数组中保存所有的Person记录,

 *  如果是这种情况,在修改个人记录时,是无需再次去查询数据库的。

 *

 *  在实际开发中,通常是从表格中选中某一行,获取到对应的NSManagedObject,然后进行修改

 *  如此,便可以只修改唯一一条记录了。

 */

- (void)updatePerson

{

    // 1. 实例化查询请求

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Book"];

    

    // 2. 设置谓词条件

    request.predicate = [NSPredicate predicateWithFormat:@"author CONTAINS '忽悠'"];

    

    // 3. 由上下文查询数据

    NSArray *result = [_context executeFetchRequest:request error:nil];

    

    // 4. 输出结果

    for (Book *book in result) {

        NSLog(@"%@ %@ %@", book.name, book.author, book.price);

        

        // 更新书名

        book.name = @"西游记";

    }

    

    // 通知上下文保存保存

    [_context save:nil];

}


/**

 *  查询所有用户记录

 */

- (void)allPersons

{

    // 1. 实例化一个查询(Fetch)请求

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];

    

    // 3. 条件查询,通过谓词来实现的

    //request.predicate = [NSPredicate predicateWithFormat:@"age < 60 && name LIKE '*'"];

    // 在谓词中CONTAINS类似于数据库的 LIKE '%%'

     /request.predicate = [NSPredicate predicateWithFormat:@"phoneNo CONTAINS '1'"];

    // 如果要通过key path查询字段,需要使用%K

    //request.predicate = [NSPredicate predicateWithFormat:@"%K CONTAINS '1'", @"phoneNo"];

    // 排序 ascendingYes为递增排序,ascending为No递减排序

    NSSortDescriptor *sort = [NSSortDescriptorsortDescriptorWithKey:@"key"ascending:YES];

    [request.setSortDescriptors:[NSArrayarrayWithObject:sort]];

  或 request.sortDescriptors=@[sort];

 
// 限定查询结果的数量(每页的数量)
//setFetchLimit
[requestsetFetchLimit:10];
// 查询的偏移量(查询多少条以后的数据 一般是: 页数 * 每页的数据量)
//setFetchOffset
[requestsetFetchOffset:1];

    // 2. _context执行查询数据

    NSArray *array = [_context executeFetchRequest:request error:nil];

    for (Person *p in array) {

        NSLog(@"%@ %@ %@", p.name, p.age, p.phoneNo);

        

        // CoreData中,查询是懒加载的

        // CoreData本身的SQL查询中,是不使用JOIN的,不需要外键

        // 这种方式的优点是:内存占用相对较小,但是磁盘读写的频率会较高

        for (Book *b in p.books) {

            NSLog(@"%@ %@ %@", b.name, b.price, b.author);

        }

    }

    

//    for (Book *b in array) {

//        NSLog(@"%@ %@ %@", b.name, b.price, b.author);

//    }

}


- (void)queryAllbook

{

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Book"];

    NSArray *arr = [_context executeFetchRequest:request error:nil];

    for (Book *p in arr)

    {

        NSLog(@"%@ %@ %@", p.name, p.price, p.author);

        

        // CoreData中,查询是懒加载的

        // CoreData本身的SQL查询中,是不使用JOIN的,不需要外键

        // 这种方式的优点是:内存占用相对较小,但是磁盘读写的频率会较高

        for (Person *b in p.persons) {

            NSLog(@"%@ %@ %@", b.name, b.age, b.phoneNo);

        }


    }

}