写这个是对coredata这个内置的数据库的一个总结
默认读者已经对 coredata 有了基本了解,并未涉及 relationships 等高级功能,只是对coredata的各类基本操作做个总结
通过这些简单的命令,可以让您很快做好一个数据库的操作,轻松构建 todo 或记事本等需要操作本地数据库的 app
一,准备工作
1,创建项目的时候,勾选“**Use Core Data
**”。完毕后在 **AppDelegate
** 中,会生成相关代码。
如果想在已有的项目中新集成 coredata 请参考这里
2,打开项目中的 xcdatamodeld 文件,在右边的数据模型编辑器的底部工具栏点击 Add Entity 添加实体。
同时在属性栏中对实体命名进行修改,并在 **Attribute
** 栏目中添加 **userID
,userName
,userImage
** 三个属性用以存储客户基本资料。
3,还要为每一个实体生成一个对应的 **NSManagedObject
** 子类,通过类的成员属性来访问和获取数据。
新建选择 **Core Data
** 项下面 **NSManagedObject subclass
** 类型文件,生成该实体同名的类。
这一步不做也可以,不做就是用kvc的方式访问,但做了可以用访问器下标的方式访问
真正用起来方便很多,不容易出错外,访问器的效率还比kvc高那么点,建议生成该类
当然这中间有个坑,放在最后说
4,下面就是很正常的勾选和选择存放地点
语言 swift
二,Core Data的使用
开始代码之前先了解几个概念
(1)NSManagedObjectModel(被管理的对象模型) 相当于实体,不过它包含 了实体间的关系
(2)NSManagedObjectContext(被管理的对象上下文) 操作实际内容
作用:插入数据 查询 更新 删除
(3)NSPersistentStoreCoordinator(持久化存储助理) 相当于数据库的连接器
(4)NSFetchRequest(获取数据的请求) 相当于查询语句
(5)NSPredicate(相当于查询条件)
(6)NSEntityDescription(实体结构)
(7)后缀名为.xcdatamodel的包 里面的.xcdatamodel文件,用数据模型编辑器编辑
编译后为.momd或.mom文件,这就是为什么文件中没有这个东西,而我们的程序中用到这个东西而不会报错的原因
了解后我们可以开始码田了
1,首先在代码中引入CoreData库###
import CoreData
2,为了方便访问,把同样的东西先放进class###
class CoreDataFunc: NSObject {
//1 在我们想要保存或者获取任何数据之前我们必须获取NSManagedObjectContext,理解为暂存器
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
//2 entity的名字
let entityName:String = "UserData"
//3 系统想要的读取数据的entity
var fetchRequest : NSFetchRequest{ return NSFetchRequest(entityName:entityName) }
}
3,保存数据###
用法:data 传 ["ID", "名字", "头像"]
func saveCoreData(data:[String]){
//为每一个实体生成一个对应的 NSManagedObject 子类,通过类的成员属性来访问和获取数据。新建选择 Core Data 项下面 NSManagedObject subclass 类型文件,生成该实体同名的类
let user = NSEntityDescription.insertNewObjectForEntityForName(entityName, inManagedObjectContext: managedContext) as! UserData
//然后就可以用下标方式赋值
user.userID = data[0]
user.userName = data[1]
user.userImage = data[2]
// 把‘暂存器’中的东西存到磁盘中
do{
try managedContext.save()
print("save success")
}catch{
print("Could not save!")
}
}//func saveCoreData(){
如果上面没有生成 subclass ,那存储的方式就得将 do 之前的内容变成如下内容
let entity = NSEntityDescription.entityForName(entityName, inManagedObjectContext: managedContext)
let user = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
user.setValue(data[0], forKey: "userID")
user.setValue(data[1], forKey: "userName")
user.setValue(data[2], forKey: "userImage")
4,获取所有数据###
key 参数为 attribute 的值,
返回类型可以随便选,这里初定为只返回名字,当然也可以返回所有数据
func loadCoreData(key key:String = "userName") -> [String]{
var result : [String] = []
do{
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
for each in fetchedResults{
let name:String = each.valueForKey(key) as! String
result.append(name)
}
print("read success")
}catch{
print("load Data from coreData error")
}
return result
}//loadCoreData
5,查询记录###
用法:条件输入查询条件 condition = "userID= '1' "
条件 condition 为nil的时候则返回所有资料,和 loadCoreData 功能相同
func searchCoreData(condition:String?) -> [UserData]?{
//必须使用新 fetch
let fetchRequest:NSFetchRequest = NSFetchRequest()
fetchRequest.fetchLimit = 10 //限定查询结果的数量
fetchRequest.fetchOffset = 0 //查询的偏移量
//设置数据请求的实体结构
fetchRequest.entity = NSEntityDescription.entityForName("UserData", inManagedObjectContext: managedContext)
//设置查询条件,条件为nil的时候则返回所有资料
if let _ = condition {
fetchRequest.predicate = NSPredicate(format: condition!, "")
}
//查询操作
do {
let fetchedObjects:[AnyObject]? = try managedContext.executeFetchRequest(fetchRequest)
guard fetchedObjects?.count > 0 else { return nil}
return fetchedObjects as? [UserData]
}
catch {
fatalError("could not search:\(error)")
}
}
这里可以使用的条件很丰富,相当于 where 在数据库中的用法
where userID == 1的情况,用于查询
"userID= '1' "
主要牵扯到 NSPredicate 的用法
NSPredicate(format: "userName= 'dafadsf' ", "")
userName == dafadsf 的情况
>NSPredicate(format: "SELF MATCHES %@", "^[A-Za-z].+") //判断字符串首字母是否为字母
Format:
(1)比较运算符>,<,==,>=,<=,!=
可用于数值及字符串
例:@"number > 100"
(2)范围运算符:IN、BETWEEN
例:"number BETWEEN {1,5}"
"address IN {'shanghai','beijing'}"
(3)字符串本身:SELF
例:"SELF == 'APPLE'"
(4)字符串相关:BEGINSWITH、ENDSWITH、CONTAINS
例:"name CONTAINS[cd] 'ang'" //包含某个字符串
"name BEGINSWITH[c] 'sh'" //以某个字符串开头
"name ENDSWITH[d] 'ang'" //以某个字符串结束
注:[c]不区分大小写[d]不区分发音符号即没有重音符号[cd]既不区分大小写,也不区分发音符号。
(5)通配符:LIKE
例:"name LIKE[cd] 'er'" // * 代表通配符,Like也接受[cd].
"name LIKE[cd] '???er*'"
(6)正则表达式:MATCHES
例:let regex = "^A.+e$"; //以A开头,e结尾
"name MATCHES %@",regex
基本可以应付常见情况了
6,删除单条数据
condition 同上的条件用法
func delCoreData(condition : String){
//设置查询条件
fetchRequest.predicate = NSPredicate(format: condition, "")
//查询操作
do {
let fetchedObjects:[AnyObject]? = try managedContext.executeFetchRequest(fetchRequest)
guard fetchedObjects?.count > 0 else { print("not found in coredata"); return }
managedContext.deleteObject(fetchedObjects![0] as! NSManagedObject)
try managedContext.save()
print("del success")
}catch{
print("CoreData delete data fail")
}
}//func delCoreData
7,删除所有数据###
该条多用于退出app时删除所有记录
不过不知道出于什么原因,苹果在 ios9 之前都没有相关的方法提供可以一次性的删除所有数据
最常见的做法是用删单条的方法建立 for 循环一个一个删,这样的后果就是效率很低
所以最快的方法就是把生成的 sqlite 数据文件整个删除,swift 2 中删除方法如下
func removeCoreData(){
guard let psc = managedContext.persistentStoreCoordinator else { return }
guard let store = psc.persistentStores.last as NSPersistentStore? else { return }
let storeUrl = psc.URLForPersistentStore(store)
managedContext.performBlockAndWait() {
self.managedContext.reset()
do{
try psc.removePersistentStore(store)
try NSFileManager.defaultManager().removeItemAtURL(storeUrl)
try psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeUrl, options: nil)
print("remove coredata file success!")
}catch{
print("remove coredata file error")
}
}//managedContext.performBlockAndWait()
}//func removeCoreData()
ios 9 以后出来的方法
if #available(iOS 9.0, *) {
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
// delegate objects
let myManagedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let myPersistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator
// perform the delete
do {
try myPersistentStoreCoordinator.executeRequest(deleteRequest, withContext: myManagedObjectContext)
} catch let error as NSError {
print(error)
}
return
}//if #available(iOS 9.0, *)
ok,可以这样调用
删除整个数据库内容
CoreDataFunc().removeCoreData()
删除 userName 等于 12331 的记录
CoreDataFunc().delCoreData("userName= '12331'")
显示所有记录
func show(){
guard let d = CoreDataFunc().searchCoreData(nil) else { print("no data in coredata"); return }
for i in d {
print(i.userID, i.userName, i.userImage)
}
}
保存一条信息
let data = [ "12", "12adsfasdfasdf", "baidu"]
CoreDataFunc().saveCoreData(data)
中间建立 subclass 有个坑######
某些特殊的情况下,建立 subclass 存储的时候会发现无法存储的情况,这时候要在 这个subclass 文件前加上
@objc(className)
例:
@objc(UserData)
class UserData: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
}
以上