固执的咀嚼里,是知识贫瘠的变现!起名

重临狼群

本人把CoreData叫做大宝剑,为啥吧,因为CoreData用起来确实让人备感舒爽~~这一篇让大家来详细的打听一下大宝剑~

花了几天时间把李微漪写的《再次来到狼群》那本书读完了。读完将来,总以为该下笔写点什么,才不辜负那样多天花在地点的时刻。

  • 参照书籍:CORE DATA by Tutorials

书里的故事是美的,以至于我在掩上书后,整个人都微微飘忽,思绪仍游离在李微漪跟格林的社会风气里,难以自拔。可故事背后蕴藏的深意更是值得人深思的,若不写点自己的感想,犹如吃了一顿可口的大餐最终却从未拉出来一样不吐不快。

  • 默认有swift基础。
  • 默许已阅读上一篇内容。

《再次回到狼群》是一部由达卡姑娘李微漪写的四十多万字的活着纪实小说,记录她要好在若尔盖大草原写生时,偶然间救起一只出生几天岌岌可危的小狼崽(后起名为格林),并带回人类世界抚养长大,最终成功放归的故事。

这一篇主要内容:

李微漪与格林

  • 深切通晓CoreData对象;
  • 创造自己的栈;
  • data model中的Relationships属性;
  • 剔除数据;

在没读那本书从前,我对狼族的摸底知之甚少,连仅有的那点对狼“凶横、暴虐、狡黠”的回味,也是源于学生时期的课本上。


蒲松龄的《狼》:驰担持刀,狼不敢前,眈眈相向/久之,目似暝,意暇甚/转视积薪后,一狼洞其中,意将隧入以攻其后也/乃悟前狼假寐,盖以诱敌。以及《狼来了》和童谣《小兔子乖乖》,无不在向我们传达着狼的“狡黠、无情”这一定义。现世的人一提起狼也是一副“谈狼色变”的形容,可知,狼留在大千世界内心的,是一道很难抹去的胆战心惊阴影。

(1)、深刻摸底CoreData对象

事先在大家创立工程的时候勾选了Use
CoreData
的挑三拣四框,勾选那一个选项框未来在AppDelegate.swift中自动生成了以下多少个对象:

  • NSManagedObjectModel
  • NSPersistentStore
  • NSPersistentStoreCoordinator
  • NSManagedObjectContext

在这一篇中我们不勾选那些选项框,自己添加那多个类以便于详细学习“大宝剑”。像这么:

不勾选


NSManagedObjectModel是什么?
本条目的就是您的data model,代表了其中的每一个对象类型。
您可以把他看成是你的数据库的图形化呈现。呼呼~~和“度娘”的演说差不离。

Note:如何将该目的与data model联系起来?
来看这几个法子:

        let modelURL = NSBundle.mainBundle().URLForResource("CoreDataTest3", withExtension: "momd")!

通过那一个主意,编译器将data
model文件编译将来放入了一个.momd文本夹,并回到了那么些文件夹的地方,通过这些地址大家起始化了大家的NSManagedObjectModel对象。


NSPersistentStore是什么?
不论是你说了算拔取哪类情势来进行仓储你都得使用NSPersistentStore来进展仓储或者读写多少。CoreData提供了几种原子操作对象和一种非原子操作对象。
原子操作对象在你操作任何读写操作从前将数据总体读写到内存中,非原子操作对象则相反,在必要的时候加载数据。

来探视那各个NSPersistentStore对象

  • NSQLiteStoreType支持SQLite数据库。他是CoreData中绝无仅有的非原子操作存储类型。那基本是多数接纳最好的选项了,xcode在默许状态下利用的就是那种存储类型。
  • NSXMLStoreType辅助XML文件,那是一种可读的囤积类型。那是一种原子操作类型,只在OS
    X上行使
  • NSBinaryStoreType支持二进制文件,原子操作类型,很少在品种中用到。
  • NSInMemoryStoreType是一个对内存中的多寡举行仓储的门类,所以那并不是一个正真的“持久化”存储类型。存储在内存中牵动测试,但并没有落成数量持久化。

NSPersistentStoreCoordinator是什么?
那是NSManagedObjectModel和NSPersistentStore之间的大桥。他能够向NSManagedObjectModel发送新闻并储存,也可以从NSPersistentStore中读取信息。


NSManagedObjectContext是什么?
那是大家事先唯一见到过的一个品种了。大家早就提到过这个特点(更加多特点后边的稿子会涉及):

  • 在内存中也就是大家一贯说的‘暂存器’中工作。
  • 有如前边所说CoreData的别样操作的率先步就是创办NSManagedObjectContext对象。
  • 在你利用save()方法从前,你的别的改变都不会影响我们磁盘中的数据

上述内容不通晓也没事,因为大家会一个一个行使的。

可实际上,狼真就是大千世界心中所想的那么如“恶魔”般存在吗?

(2)、自己来创设一个栈

创办一个新文件CoreDataStack.swift(在这么些文件中,咱们将自己加上全套事先xcode自动生成的代码,以便于对那多少个目标的领悟),添加以下代码:
<pre><code>
import CoreData
class CoreDataStack {
let context:NSManagedObjectContext!
let psc:NSPersistentStoreCoordinator!
let model:NSManagedObjectModel!
let store:NSPersistentStore!

init() {
    //1
    let bundle = NSBundle.mainBundle()
    let modelURL = bundle.URLForResource("CoreDataTest3", withExtension:"momd")
    model = NSManagedObjectModel(contentsOfURL: modelURL!)
    //2
    psc = NSPersistentStoreCoordinator(managedObjectModel:model)
    //3
    context = NSManagedObjectContext()
    context.persistentStoreCoordinator = psc
    //4
    let fileManager = NSFileManager.defaultManager()
    let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) as! [NSURL]
    let documentsURL = urls[0]
    let storeURL = documentsURL.URLByAppendingPathComponent("Dog Walk")
    let options = [NSMigratePersistentStoresAutomaticallyOption: true]
    var error: NSError? = nil
    store = psc.addPersistentStoreWithType(NSSQLiteStoreType,
        configuration: nil, URL: storeURL, options: options, error:&error)
    if store == nil {
        println("Error adding persistent store: \(error)")
        abort()
    }
}
func saveContext() {
    var error: NSError? = nil
    if context.hasChanges && !context.save(&error) {
        println("Could not save: \(error), \(error?.userInfo)") }
}

}

}
</code></pre>

瞬间添加了这么一大块代码,一眼看千古势必是晕晕的,好的,一句一句来解释一下吧。

  • 第一添加了三个常量,那多个常量就是我们前边讲了很久的那四个CoreData的对象,而接下去的伊始化方法就是对那多个常量举行开头化。
  • 初始化函数。
  • //1 前边早已说过了NSManagedObjectModel代表着大家的data model。
    let modelURL = bundle.URLForResource(“CoreDataTest3″,
    withExtension:”momd”)
    其一法子将data
    model编译成一个‘momd’文件,并赶回她的地址,NSManagedObjectModel对象则是由此这么些地点来进展伊始化。
  • //2 对NSPersistentStoreCoordinator进行初步化,他是data
    model与‘暂存器’NSManagedObjectContext之间的大桥。
  • //3
    对‘暂存器’NSManagedObjectContext举行早先化,并与大家的‘桥梁’连接起来。
  • //4 通过
    func addPersistentStoreWithType(storeType: String, configuration:
    String?, URL storeURL: NSURL?, options: [NSObject : AnyObject]?,
    error: NSErrorPointer) -> NSPersistentStore?
    主意对NSPersistentStore进行发轫化,在这边大家指定了persistent
    store类型。
  • 末段大家添加了保留方法,也就是将‘暂存器’context保存到磁盘中,代码很不难通晓,就不开展诠释了。

上述增进的代码仔细观察的话,很不难就会发现基本就是在大家勾选了 use
core data
未来xcode自动生成的代码,而我辈只是将它写在了一个类中,以方便观望及精通。


像大家地方那样创造了一个类,不过那一个类根本未曾加入到大家的主次中来,接下去就是将那个类参预到程序中。
开辟AppDelegate.swift,添加以下代码:

         import CoreData

          lazy var coreDataStack = CoreDataStack()

如此一来coreDataStack这些变量就拥有了大家事先写的两个目标了。
在底下多少个方法中添加coreDataStack.saveContext():

<pre><code>
func applicationDidEnterBackground(application: UIApplication) {
coreDataStack.saveContext()
}
func applicationWillTerminate(application: UIApplication) {
coreDataStack.saveContext()
}
</code></pre>

那俩方法确定应用在暴发意外退出的时候保存数据,使数据不会丢掉。


再来观察一下大家的文件目录,哦~我们还差一个.xcdatamodeld文件,那么就来新建一个啊。
右击文件目录->New file…->接纳iOS Core Data->选取Data
Model->next->命名为‘CoreDataTest3’,像这么:

1.png

今日来看大家的次序就和勾选了use core
data
分选一模一样了,接下去就可以展开前边两篇的操作,而且意义等同。哦~唯一的区分就是行使coreDataStack.context来替代前边篇章中AppDelegate.swift中的managedObjectContext。


读了《重临狼群》后,我根本推翻了原先对狼的回味。我从李微漪笔下认识的狼,它们重情重义、忠诚可信赖、甚至憨萌可爱。

(3)、relationships属性和删除功效

接下去的始末,我们因而一个Demo,来演示一下data
model中的relationships属性和删除效能。
开辟storyboard删除原有的控制器,拖入一个tableviewcontroller,并将之设置为顺序人口,如图所示:

勾选藏红色框内的抉择框

再为这一个控制器创设一个类,如以下步骤:
New File->接纳iOS Source,继续选用cocoa touch
class->next->将其拔取为UITableviewController的子类->next->Create

3.jpeg

同时将控制器和咱们新建的公文进行绑定。

4.png

将控制器转化为Navigationcontroller,日图操作:

先选中控制器

给navigation Bar添加一个right Button,并添加动作‘add提姆e’,添加代码。
将完毕以下功效,由于那段落成并不复杂,在此处就不开展描述,有标题的可以留言。

点击“+”按钮,在底下列表中丰硕时间

眼下以此本子并不曾兑现多少持久化,当我们脱离应用未来数据将荡然无存,接下去大家做的就是将数据持久化,那听起来好像在前两篇大家曾经做过了,不然~~~在此地大家将推举relationships的定义,同时落到实处删除成效。


  • relationships

其一逻辑是如此的,大家需求一个数组来存放时间,大家暂且把那么些数组叫做‘时间组’,这一个‘时间组’存放了重重时刻,那么这些时刻组就是一个Entity,里面存放的时光也是Entity,不过时间组这几个Entity的每一个目标都拥有许多的大运Entity,先来创制那五个Entity,一个起名为“提姆eArry”,一个起名为“提姆e”,在”提姆e”这么些Entity中有一个品质time类型选择为NSDate:

1.png

而在“提姆eArry”中则设有一个relationship,起名为“times”,指向“提姆e”Entity:

Note:relationship生成的属性是哪些项目标?“To
Many”生成的是NSSet类型,即使想行使下标来来使用对象的话,请在左侧的属性栏中勾选Ordered选料,当您勾选了那一个选项未来生成的“To
Many”类型就是NSOrderedSet类型。
在此间大家接纳NSOrderedSet类型

革命框内为Relationship属性

同时将Type选择为“To Many”,勾选Ordered

勾选Ordered

给大家的多少个Entity生成对象类吧,生成方法在上一篇中一度讲过:
Editor—>Create NSManagedObject Subclass ………….

率先要丰盛的代码当然是addTime方法来添加多少,在此方法中添加以下代码:
<pre><code>
@IBAction func addTime(sender: AnyObject) {
//获取当前光阴
let date=NSDate()
//1
let entity = NSEntityDescription.entityForName(“Time”,
inManagedObjectContext: managedContext)
let TimeObject = Time(entity: entity!, insertIntoManagedObjectContext:
managedContext)
TimeObject.time=date

    //2 Insert the new times into the TimeArry's times set
    var times = timearry.times.mutableCopy() as! NSMutableOrderedSet
    times.addObject(TimeObject)
    timearry.times = times.copy() as! NSOrderedSet

    //3 Save the managed object context
    var error: NSError?
    if !managedContext!.save(&error) {
        println("Could not save: \(error)")
    }

    //4
    let timeFetch = NSFetchRequest(entityName: "TimeArry")
    let result = managedContext.executeFetchRequest(timeFetch, error: &error) as! [TimeArry]!
    self.timearry=result[0]
    self.tableview.reloadData()
}

</code></pre>

代码解释:

  • //1 初步化一个“提姆e”对象实例。
  • //2
  • 初始化times属性
  • 将事先的“提姆e”对象实例
  • 添加到relationships中
  • 将relationship添加到当前来得的“提姆eArry”
  • //3 保存数据
  • //4 更新timearry数组

Note:timearry就是我们在界面上显得的“TimeArry”对象的一个实例,按理来说提姆eArry有很三个目标,每一个“提姆eArry”对象都有投机的“提姆e”,那样说起来好像很像一个二维数组,而实质上我们只体现了那一个二维数组的第一行。那么在进入程序的时候我们就得创造那个timearry对象。

增进一下代码:
<pre><code>

var timearry:TimeArry!
override func viewDidLoad() {
super.viewDidLoad()
//起头化暂存器
let appDelegate = UIApplication.sharedApplication().delegate as!
AppDelegate
managedContext = appDelegate.coreDataStack.context
//1 获取“提姆eArry”对象,并开始化timearry
var error: NSError?
let timeFetch = NSFetchRequest(entityName: “TimeArry”)
let result = managedContext.executeFetchRequest(timeFetch, error:
&error) as! [TimeArry]!
if result.count == 0 {
let entity = NSEntityDescription.entityForName(“TimeArry”,
inManagedObjectContext: managedContext)
self.timearry = TimeArry(entity: entity!,
insertIntoManagedObjectContext: managedContext)
}else{
self.timearry=result[0]
}
// 添加Edit按钮
self.navigationItem.leftBarButtonItem = self.editButtonItem()
}
</code></pre>

那段代码很简单驾驭(如若你看了自己前边的两篇内容的话),就是读取了“提姆eArry”的始末,然后若是存在数据,则使timearry为第一组数据,若不存在多少则初步化。

因为大家是用一个tableview来彰显数据,所以添加以下代码:
<pre><code>
override func numberOfSectionsInTableView(tableView: UITableView) ->
Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return self.timearry.times.count
}
</code></pre>
就不对那段代码做表明了,我们应该都懂。

接下去就是在界面上出示数据了:
<pre><code>

override func tableView(tableView: UITableView, cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(“cell”,
forIndexPath: indexPath) as! UITableViewCell

    var fmt=NSDateFormatter()
    fmt.dateFormat = "yyyy-MM-dd-hh-mm-ss"
    let date = self.timearry.times[indexPath.row] as! Time
    let showtime = fmt.stringFromDate(date.time)
    cell.textLabel!.text = showtime
    return cell
}

</code></pre>

“timearry”那些目的的times属性就是大家要读取的情节,你可以把他当做一个数组来操作,因为他也可以用下表来获取期中的每一个多少。
若你在以前data
model
不曾勾选Ordered则在那边生成的times是NSSet类型,那么就不可以用下标来取得内容了。

今日来运转下app:

退出app,重新登录数据还在,表达保存数据成功


近日来添加删除成效,以下代码:
<pre><code>

// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return NO if you do not want the specified item to be editable.
    return true
}    
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
    //1
    let timeToRemove = self.timearry.times[indexPath.row] as! Time
    //2
    let times = self.timearry.times.mutableCopy() as! NSMutableOrderedSet
    times.removeObject(timeToRemove)
    self.timearry.times = times.copy() as! NSOrderedSet
    //3
    managedContext.deleteObject(timeToRemove)
    //4
    var error: NSError?
    if !managedContext.save(&error) {
        println("Could not save: \(error)")
    }

    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    } else if editingStyle == .Insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }    
}

</code></pre>

先是个点子添加左滑编辑效率。
来表达下首个措施,当你点击Delete会调用此方法:

  • 第一获得要刨除的目的
    • 先获取NSOrderedSet对象
  • 从中删除对象

  • 同步到self.timearry.times
  • 从内存中删除对象
  • 保存‘暂存器’

功勋卓著告成,这一篇写的好困难啊,逻辑混乱,有看不懂的娃儿,实在不佳意思了,不了解的局地请留言,我来解释。
末段运行一下吧:

劳苦功高告成

源代码已上传Github:https://github.com/superxlx/CoreDataTest3

任凭冒着生命危险为饥馑中的妻儿偷袭羊群而惨死人类屠刀下的格林四叔,依然巨大殉情自杀的格林二姑,再到后来趴在受伤的“敌人”——藏獒黑虎背上为其舔舐疗伤的、以及没日没夜在户外默默等候病重的李微漪的格林,都无一不在撞击着自家的神魄,刷新着自我对狼族的认识。这一个温情脉脉的一瞬,无论怎么着都心有余而力不足让自家将狼跟冷酷严酷联系起来。

李微漪与格林

只能说,大家从小接受的关于狼的指引,都太过偏颇。狼因猎食家畜,成为人类的眼中钉,人类就站在投机的补益场上,给狼安上各类臭名昭著的“罪名”,甚至中国连含有贬义的成语,狼都没能幸免,如:狼心狗肺、声名狼藉、一丘之貉等,都一一把狼给恶意的丑化。

倘若硬要把狼这一猎食家畜行为说成是穷凶极恶狡诈,这也是在并日而食时生物面对食品作出的最本能反应。根据世代生活在草地上牧民的布道,狼本是足以与人和平共处的,如若食物丰富充沛,它们也绝不愿意闯进人类的国土来抢夺食品。

唯独,随着过度放牧越来越严重,草原日趋沙化,草场上的生物体品种日趋单一,意味着狼赖以生活的食品,也逐步稀少。在食物短缺饥饿的驱使下,狼不得不把茅头指向人工喂养的动物。换句话说,是全人类过度放牧霸占了狼的家庭,不仅吸引草原风险,还致使狼的饔飧不继。反过来,狼就不得不因食品短缺而闯入人类地盘去获取食物。这就是所谓的有果必然有其因,那最大的“因”就是全人类自己呀!

正如李微漪说的:狼,不是草原的害兽,自然界最可怕的不是“兽行”,而是“人为”!

呆萌的小格林

相比较之下起人类对狼的畏惧、憎恨,我想,狼对人类才更应该感到毛骨悚然与憎恨才对。

李微漪在若尔盖大草原上,最怕的不是碰到飞禽猛兽,而是草原上人类对狼作出的“兽行”。

有一些人在金钱利益的主旋律下,杀狼不眨眼。它们为了可以拿到狼的肤浅,在狼常出没的地面布下狼夹子。狼一旦被狼夹子夹到了,要么就唯有等死被人类剥掉狼皮换取高额的价位;要么就咬断自己被夹的腿才能逃生,可失去腿后的狼因为行动不便不可能再捕获到猎物,最终也只有活活被饿死。反正无论怎么样,对狼来说都是死。由此,比起阴毒,有些人类大概是有过之而无不及。

实在,话说回来,在自然界的食品链中,没有哪个人对哪个人错,每个物种之间都有吃与被吃的涉嫌。羊吃草、狼吃羊,就如同鸡吃虫、人吃鸡一样健康。人类不可以只是地由于自身利益保留对团结方便的生物,而消灭自己讨厌的浮游生物,那是极为自私跟不人道的。

就此,恶意地去丑化狼族,是人类在文化贫瘠与便宜驱使下偏执的显示,对狼来说有所偏向。也希望大家前途的指引,能走出对狼的执拗认知里,还狼一个当真公允的身价,那才是当做食品链最上方的人最应当做的!

相互信任

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图