第二个实例是一个领结管理程序。在这个程序中,你可以切换不同颜色的领带,R代表红色,O代表橘黄色。点击任意颜色会加载对应颜色的领结并显示该领结的一些信息,包括:
- 领结的名称
- 你带过多少次这款领结
- 最近一次带的时间
- 你是否喜欢这款领结
转载请注明出处:http://blog.csdn.net/yamingwu/article/details/42235929
源代码地址:https://github.com/dnawym/StudySwift/tree/master/CoreData/Bow%20Ties
点击Wear按钮会增加该款领结的使用次数并更新最后一次带的时间。
点击Rate按钮可以修改你对该款领结的评分,评分是0-5的十进制数。
数据建模:
Core Data可以支持多种数据类型,除了第一节中使用的String,还可以支持Integer,Data,Double,Binary Data,Transformable等等。
其中,binary data用于存储如图片,pdf等可以序列化的数据。如果要存储的图片很大,将图片数据存入数据库则会降低Core Data的性能,因为每次访问一个entity都会将整个数据加载到内存中。这是就需要使用binary data的’Allow External Storage'选项,这样Core Data会自行判断应该将数据存入到数据库还是存储一个指向目标文件的URI。
存储非标准数据到Core Data中:
当我们要存储类似UIColor数据到Core Data中时,可以为UIColor定义Transformable类型的Core Data attribute,Core Data就可以帮我们对UIColor进行序列化和反序列化。只要符合NSCoding protocol的类,都可以使用这种方式。这样就不用在存储UIColor前手动进行序列化,在读取数据后,手动进行反序列化操作。
创建ManagedObject的子类
在第一个例子中我们使用了KVC方式来操作Core Data - Person,但是使用字符串方式编程很容易导致bug,因为字符串不像强类型,没有语法检查,很容易拼错。
创建BowTie类:
这就会创建如下的swift文件:
import Foundation
import CoreData
class Bowtie: NSManagedObject {
@NSManaged var name: String
@NSManaged var isFavorite: NSNumber
@NSManaged var lastWorn: NSDate
@NSManaged var rating: NSNumber
@NSManaged var searchKey: String
@NSManaged var timesWorn: NSNumber
@NSManaged var photoData: NSData
@NSManaged var tintColor: AnyObject
}
最后做如下修改就创建好了managed object的子类:
接下来我们测试一下我们创建的Core Data能否正常工作,在AppDelegate.swift中加入以下代码:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// save test bow tie
let entity = NSEntityDescription.entityForName("Bowtie", inManagedObjectContext: managedObjectContext!)
let bowtie = Bowtie(entity: entity!, insertIntoManagedObjectContext: managedObjectContext)
bowtie.name = "My bow tie"
bowtie.lastWorn = NSDate()
managedObjectContext?.save(nil)
// retrieve test bow tie
let request = NSFetchRequest(entityName: "Bowtie")
let ties = managedObjectContext!.executeFetchRequest(request, error: nil) as [Bowtie]
let sample = ties[0]
println("Name: \(sample.name), Worn: \(sample.lastWorn)")
return true
}
这段代码在程序启动时创建一个名为‘my bow tie'的Bowtie对象,并设置lastWorn日期为今天,并插入到CoreData中。
然后,fetch所有的Bowtie实例并打印第一条领带的名字和最近一次佩戴时间。
在项目的其它文件中使用Managed Context:
在ViewController.swift中添加声明和定义
import CoreData
var managedContext: NSManagedObjectContext!
修改AppDelegate,将managedObjectContext传递给ViewController,去掉appDelegate中的测试代码
let viewController = self.window!.rootViewController as ViewController
viewController.managedContext = self.managedObjectContext
接下来,我们读取plist中的数据来初始化Core Data数据库
函数insertSampleData查看CoreData中是否有领带的数据,如果有则返回,如果没有责将SampleData.plist中的数据插入到Core Data数据库中。
而colorFromDict用于将plist中存放的颜色对应的3原色转换为UIColor。
这里需要注意:
- 存储image到core data时,我们先从文件系统中读取图片构造UIImage,然后通过UIImagePNGRepresentation转换UIImage为NSData,最后将转换后的数据存入imageData中
- 存储color时,由于color被存储在transformable属性中,我们不需要做其它特殊操作就能够将颜色存入tintColor中。
// Insert sample data
func insertSampleData() {
let fetchRequest = NSFetchRequest(entityName: "Bowtie")
fetchRequest.predicate = NSPredicate(format: "searchKey != nil")
let count = managedContext.countForFetchRequest(fetchRequest, error: nil)
if count > 0 {
return
}
let path = NSBundle.mainBundle().pathForResource("SampleData", ofType: "plist")
let dataArray = NSArray(contentsOfFile: path!)
for dict : AnyObject in dataArray! {
let entity = NSEntityDescription.entityForName("Bowtie", inManagedObjectContext: managedContext)
let bowtie = Bowtie(entity: entity!, insertIntoManagedObjectContext: managedContext)
let btDict = dict as NSDictionary
bowtie.name = btDict["name"] as NSString
bowtie.searchKey = btDict["searchKey"] as NSString
bowtie.rating = btDict["rating"] as NSNumber
let tintColorDict = btDict["tintColor"] as NSDictionary
bowtie.tintColor = colorFromDict(tintColorDict)
let imageName = btDict["imageName"] as NSString
let image = UIImage(named: imageName)
let photoData = UIImagePNGRepresentation(image)
bowtie.photoData = photoData
bowtie.lastWorn = btDict["lastWorn"] as NSDate
bowtie.timesWorn = btDict["timesWorn"] as NSNumber
bowtie.isFavorite = btDict["isFavorite"] as NSNumber
}
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error!.userInfo)")
}
}
func colorFromDict(dict: NSDictionary) -> UIColor {
let red = dict["red"] as NSNumber
let green = dict["green"] as NSNumber
let blue = dict["blue"] as NSNumber
let color = UIColor(red: CGFloat(red)/255.0, green: CGFloat(green)/255.0, blue: CGFloat(blue)/255.0, alpha: 1)
return color
}
在我们将领结数据存入CoreData后,通过viewDidLoad来读取数据
override func viewDidLoad() {
super.viewDidLoad()
insertSampleData()
let request = NSFetchRequest(entityName: "Bowtie")
let firstTitle = segmentedControl.titleForSegmentAtIndex(0)
request.predicate = NSPredicate(format: "searchKey == %@", firstTitle!)
var error: NSError? = nil
var results = managedContext.executeFetchRequest(request, error: &error) as [Bowtie]?
if let bowties = results {
populate(bowties[0])
} else {
println("Could not fetch \(error), \(error!.userInfo)")
}
}
func populate(bowtie: Bowtie) {
imageView.image = UIImage(data: bowtie.photoData)
nameLabel.text = bowtie.name
ratingLabel.text = "Rating: \(bowtie.rating.doubleValue)/5"
timesWornLabel.text = "# times worn: \(bowtie.timesWorn.integerValue)"
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .ShortStyle
dateFormatter.timeStyle = .NoStyle
lastWornLabel.text = "Last worn: " + dateFormatter.stringFromDate(bowtie.lastWorn)
favoriteLabel.hidden = !bowtie.isFavorite.boolValue
view.tintColor = bowtie.tintColor as UIColor
}
这样我们就完成了读取数据并显示的工作
下一节,我们将继续完善这个程序,实现在领结间的切换,完成wear和rate按钮事件的处理,以及验证数据的有效性。