美文网首页iOS零碎知识iOS进阶不易的地方iOS学习资料整理+学习方法
斯坦福大学iOS开发公开课总结(十二 & 十三) :Co

斯坦福大学iOS开发公开课总结(十二 & 十三) :Co

作者: J_Knight_ | 来源:发表于2016-07-18 08:44 被阅读730次

第十二课和第十三课都介绍了CoreData的知识,并在十三课的中段通过一个Demo来具体实现了CoreData的操作。

笔者之前从未接触过Core Data的相关知识,因此学期这两节课比较吃力,这一篇总结还是有很多需要改进的地方,以后随着对Core Data认识的深入和对这两节课的反复咀嚼,会不断更新该总结。

开始吧!

Core Data


Core Data是一种持久化技术,它能将模型对象的状态持久化到磁盘,但它最重要的特点是:Core Data不仅是一个加载、保存数据的框架,它还能和内存中的数据很好的共事。

排除错误认识:Core Data并不是数据库! 它只是连接类(Class)和数据库(SQL)的桥梁。通过Core Data的相关功能,我们可以对数据库进行增删改查的操作。

CoreData是如何工作的呢?

1. 创建对象的可视化映射

在看到可视化映射之前,需要了解实体的概念:

实体的概念:每个实体是一个表,每个表对应一个对象。
简单粗暴的理解:实体在数据库领域叫做表,在面向对象领域叫做对象。

实体之间的关系=表之间创建关系,对象之间的关系。

注意:两个对象之间的关系在两个对象端具有不同的名称。而且关系的对应数量也是不同的:to one,to many

举个🌰 :摄影者和照片的关系:
摄影者对应多个照片,但是照片只对应一个摄影者。

那么言归正传,如何创建对象的可视化映射呢?

  1. 创建模型文件,用来装入各种需要映射的实体。
  2. 在模型内部添加实体(Entity),创建实体之间的关系(必要时)。

下面笔者录制了创建实体,增加实体属性,连接实体的操作:

创建实体,增加属性

2. 为实体创建NSManagedObjectd子类

我们需要将刚得到的可视化的实体“转变为”具体的类。在Core Data中,这些类都是NSManagedObjectd子类。

下面演示一下其创建过程:

创建NSManagedObjectd子类

以实体Photo为例,系统为我们生成了Photo.hPhoto.m

我们先看一下Photo.h:


#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

NS_ASSUME_NONNULL_BEGIN
@interface Photo : NSManagedObject
// Insert code here to declare functionality of your managed object subclass
@end
NS_ASSUME_NONNULL_END
#import "Photo+CoreDataProperties.h"

我们可以看到,Photo类继承了NSManagedObject

但是,有意思的是,系统还为我们自动生成了Photo+CoreDataProperties.hPhoto+CoreDataProperties.m,详情见动图左侧,创建实体类之后。

思考
生成这两个文件的目的是什么呢?
首先,我们首先要知道这两个文件是什么:
他们构成了Photo类的分类(Category)。

那么什么是分类呢?
通过分类,我们可以向原有的类添加方法,而不需要通过继承的方式。分类的局限是:在分类里不能再添加属性。

那么显然,通过````Photo+CoreDataProperties,我们就可以不用继承Photo类来给其添加方法。因为原有的Photo```类只具有属性,除了获取属性之外,并不能为我们做其他的事情。这时,如果可以在其他的地方给其无限地添加方法还是很具有诱惑力的。令人欣慰的是,系统可以自动为我们生成。

3. 通过创建NSManagedObjectContext访问,操作数据库

数据库创建对象,设置对象属性,查询对象都需要NSManagedObjectContext

创建NSManagedObjectContext的两个不同的方法:

1.通过其自身的初始化:

[NSManagedObjectContext alloc] init];

2.通过UIManagedDocument创建:

UIManagedDocument 用于管理存储的机制,将Core Data数据库放入某存储空间。

UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];
//url:这个core data 数据库存储的地方

数据库的操作:

1. 向数据库添加对象(实体):

[NSEntityDescription insertNewObjectForEntityForName:@"Photo" inManagedObjectContext:context];

2. 从数据库删除对象(实体):

[aDocument.managedObjectContext deleteObject:photo];

删除对象后,系统会向所有对象发送这个消息

- (void)prepareForDeletion{
 //在这里保持数据同步,比如删掉这个对象的时候会影响到其他对象的数据
 //应该在这个对象被删除前及时更新那个数据
}

3. 在数据库查询对象(实体):

我们使用NSFetchRequest类查询数据库的对象,通过设置其不同属性来查找符合不同标准的数据:

举个🌰 :查找出100个photo的实体:

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
request.fetchLimit = 100;

关于Core data的线程安全

//让context在安全队列中执行的方法
[context performBlock:^{
    [A doSomething];
}];

NSFetchedResultsController


NSFetchedResultsController的作用是将NSFetchRequest 和 UITalbleView联系到一起。
和TableView的数据源方法类似:

- (NSInteger)numberOfRowsInSection:(NSInteger)section{
  return [[self.fetchedResultsController sections] count];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
   return [[self.fetchedResultsController sections] count] objectAtIndex:section] numberOfObjects];
}

详细的使用方法会在Demo讲解部分中告诉大家。

Demo


Demo需求

  • 每隔20分钟,从flickr拿回最新的摄影者数据。
  • 用一个TableView显示当前拿回的摄影者的名字和所照的照片数。

Demo效果图

摄影师的信息列表

重要代码段

1. 在启动接口获取flickr的数组


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     self.photoDatabaseContext = [self createMainQueueManagedObjectContext];    
     [self startFlickrFetch];   
     return YES;
}

- (void)startFlickrFetch
{
    [self.flickrDownloadSession getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        if (![downloadTasks count]) {
            NSURLSessionDownloadTask *task = [self.flickrDownloadSession downloadTaskWithURL:[FlickrFetcher URLforRecentGeoreferencedPhotos]];
            task.taskDescription = FLICKR_FETCH;
            [task resume];
        } else {
            for (NSURLSessionDownloadTask *task in downloadTasks) [task resume];
        }
    }];
}

2. 每隔20分钟获取新的内容


- (void)setPhotoDatabaseContext:(NSManagedObjectContext *)photoDatabaseContext
{
    _photoDatabaseContext = photoDatabaseContext;
    
    //photoDatabaseContext设定成功后,每隔20分钟重新获取信息
    if (self.photoDatabaseContext)
    {
        self.flickrForegroundFetchTimer = [NSTimer scheduledTimerWithTimeInterval:FOREGROUND_FLICKR_FETCH_INTERVAL
                                                                           target:self
                                                                         selector:@selector(startFlickrFetch:)
                                                                         userInfo:nil
                                                                          repeats:YES];
    }
    
    //photoDatabaseContext设定成功后 向控制器发送消息
    NSDictionary *userInfo = self.photoDatabaseContext ? @{ PhotoDatabaseAvailabilityContext : self.photoDatabaseContext } : nil;
    [[NSNotificationCenter defaultCenter] postNotificationName:PhotoDatabaseAvailabilityNotification
                                                        object:self
                                                      userInfo:userInfo];
}

3. 在表格视图查询所有摄影师的名字


- (void)setManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
{
    //哪个数据库
    _managedObjectContext = managedObjectContext;
    
    NSFetchRequest *requet = [NSFetchRequest fetchRequestWithEntityName:@"Photographer"];
    requet.predicate = nil;//所有的,无过滤
    requet.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(localizedStandardCompare:)]];

    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:requet managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    
}

4. 重写tablelViwe:cellForRowAtIndex:方法,显示摄影师数据


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Photographer cell"];
    
    //拿到摄影师的名字和摄影数量
    Photographer *photographer = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = photographer.name;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%lu photos", [photographer.photos count]];    
    return cell;
    
}

本Demo显然是一个未完成品,它只显示了摄影师的相关信息,并且只有一个页面。在接下来的课程中应该会对该Demo进行更多过的扩展。

最后的话


如果哪位小伙伴想拿到本文Demo的代码请不要客气,可以进入我的GitHub下载哦~ 这一系列到现在为止的所有Demo都在里面,分为英文注释版本和中文注释版本两种。

十分欢迎给笔者的代码和文笔抛出宝贵的意见和建议~

本文已在版权印备案,如需转载请访问版权印。48422928

获取授权

相关文章

网友评论

    本文标题:斯坦福大学iOS开发公开课总结(十二 & 十三) :Co

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