您的位置:首页 > 其它

5- coreData基本扩展(保存NSArray)

2016-05-06 22:25 330 查看
http://www.jianshu.com/p/4ea1b6cbd456

一.文章概要

本篇文章主要是说明"coreData"如何利用"Transformable"类型,保存"NSArray".

整个存储的思路就是在coreData保存时,设置要保存NSArray的属性的类型为'Binary Data(二进制数据)',然后利用NSKeyedArchiver对要保存的NSArray进行转换.因为coreData没有提供可以直接保存NSArray的数据类型 逻辑如下图:



描述

关于NSArray的保存,研究了好久,最终只试验成功了这一种方案,感觉有点不合逻辑,譬如重新创建一个和实体对应的对象类.大家要是有更好的方案的话,希望能够告诉我下,不胜感激!!!


二.准备工作(关于NSKeyedArchiver)

NSKeyedArchiver归档是iOS数据持久化的方式之一.

我们使用NSKeyedArchiver可以归档和恢复NSString、NSArray、NSDictionary、NSSet、NSDate、NSNumber和NSData等基本的Foundation对象。更加具体的看这篇文章:/article/2026259.html

三.新增加保存NSArray的属性

第一步,在实体中增加属性

这里属性类型是"Binary Data",应为翻译就是"二进制数据". 添加完成后如下图:



描述

第二步,生成新的"NSManagedObject"子类文件

和上篇文章相同,不赘述.

四.创建需要保存的对象类

我这里说的对象类型是指的我们正常创建了的继承了NSObject的对象类.而不是我们上文提到coreData模型文件自动生成NSManagedObject Sublcass子类的的例如"Book+CoreDataProperties.h","Book"这些.

还有一点我要提到的是,在最开始的试验保存NSArray时候,想要直接保存上述NSManagedObject Subclass子类,到那时各种尝试始终不行,不是保存的时候报错,就是读取的时候报错


所以,这里即使我们真的要保存一个和之前实体一模一样的类型,也需要再
重新创建一个新的对应全部属性的NSObject类
.同时,又因为我们用到了NSKeyedArchiver进行归档,
所以同时还需要实现NSCoding 协议中的两个方法,分别是"encodeWithCoder"和"initWithCoder"
但是在实际代码中,我们新建的NSObject 类并没有声明要实现<NSCoing>,代码运行过程中也没有报错。


我们这里新建了名为"BookInfo的子类"具体代码如下:

BookInfo.h:

//
//  BookInfo.h
//  fmdb
//
//  Created by 李龙 on 16/1/5.
//  Copyright © 2016年 李龙. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Student.h"

@interface BookInfo : NSObject

@property (nonatomic, assign) NSNumber *bookID;
@property (copy, nonatomic) NSString *bookName;
@property (strong,nonatomic) Student *student;

@end

BookInfo.m:

//
//  BookInfo.m
//  fmdb
//
//  Created by 李龙 on 16/1/5.
//  Copyright © 2016年 李龙. All rights reserved.
//

#import "BookInfo.h"

@implementation BookInfo

- (void) encodeWithCoder: (NSCoder *)coder
{
[coder encodeObject:self.bookID forKey:@"bookID"];
//    [coder encodeObject:self.bookName forKey:@"bookName"];
[coder encodeObject:self.student forKey:@"student"];
}

- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {

self.bookID = [aDecoder decodeObjectForKey:@"bookID"];
//        self.student = [aDecoder decodeObjectForKey:@"student"];
self.bookName = [aDecoder decodeObjectForKey:@"bookName"];
}
return self;
}

@end

注意:如果你要在BookInfo的对象中保存stduent这个属性,那么按照这种方法,你还需要在创建一个平常的和实体Student对应的Student的对象类


五.保存和读取NSArray

保存NSArray



描述

保存代码如下是:

//插入数据
- (IBAction)insertData{
NSLog(@"插入数据");

//====== 3'
//第一组数据
Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.managedContext];
student.name = @"张三2";
student.id = @(11);

BookInfo *book =  [[BookInfo alloc] init];
book.bookID = @(121);
book.bookName = @"<老人与海2>";
//        book.student = student;
//        student.book = book;

BookInfo *book1 =  [[BookInfo alloc] init];
book1.bookID = @(121);
book1.bookName = @"<老人与海2>";
//        book1.student = student;

student.booksArray = [NSKeyedArchiver archivedDataWithRootObject:@[book,book1]];

//第二组数据
Student *student2 = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.managedContext];
student2.name = @"李四2";
student2.id = @(23);

BookInfo *book2 = [[BookInfo alloc] init];
book2.bookID = @(242);
book2.bookName = @"<飞鸟集2222>";
//        book2.student = student;
//        student2.book = book2;

BookInfo *book22 =  [[BookInfo alloc] init];
book22.bookID = @(242);
book22.bookName = @"<飞鸟集22222>";
book22.student = student;

student2.booksArray = [NSKeyedArchiver archivedDataWithRootObject:@[book2,book22]];

//保存,用 save 方法
NSError *error = nil;
BOOL success = [self.managedContext save:&error];
if (!success) {
[NSException raise:@"访问数据库错误" format:@"%@",[error localizedDescription]];
}
}

读取NSArray



描述

图中对应代码如下:

//读取数据库文件
- (IBAction)readData{
NSLog(@"读取数据");
dispatch_async(dispatch_get_main_queue(), ^{

// 初始化一个查询请求
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// 设置要查询的实体
request.entity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:self.managedContext];

//以上代码简写成下边
//        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];

// 设置排序(按照age降序)
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"id" ascending:NO];
request.sortDescriptors = [NSArray arrayWithObject:sort];

// 执行请求
NSError *error = nil;
NSArray *objs = [self.managedContext executeFetchRequest:request error:&error];
if (error) {
[NSException raise:@"查询错误" format:@"%@", [error localizedDescription]];
}

NSLog(@"-----------------------------------");
// 遍历数据

for (Student *stu in objs) {
//获取书的数组
NSArray *bookArr = [NSKeyedUnarchiver unarchiveObjectWithData:stu.booksArray];
NSLog(@"%@",bookArr);
for (BookInfo *book in bookArr) {
NSLog(@"bookInfo:%zd-----%@-----%@",book.bookID,book.bookName,book.student);
}
}
});
}

六.小结

到这里保存NSArray的这种方式就写完了. 大家也可以注意到,这个方法保存数组,数组对象中或者数组对象保存的属性中不能出现NSEntityDescription得到的对象子类.

具体的 Demo 代码可以在我的 GitHub 上找到
Demo地址

我一时间也想不到其他的好方法,希望有其他方法保存NSArray朋友能够分享下.

希望能和大家交流技术

欢迎大家关注我的微博和我GitHub,我会不时分享和转发一些大牛的技术贴和开源项目.

新浪微博:http://weibo.com/1594425143/profile?topnav=1&wvr=6&is_all=1

GitHub:https://github.com/lilongcnc

博客地址:http://www.lilongcnc.cc

文/春田花花幼儿园(简书作者)

原文链接:http://www.jianshu.com/p/4ea1b6cbd456

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: