增加和删除改查澳门威尼斯人网址,从入门到领会

大家的生活态度就相应是 “不埋怨” !

在上篇博客中,讲了数据模型和 CoreData
栈的创始,那下一步便是对数码的操作了。和数据库一样,CoreData
里的操作也唯有是增加和删除改查。下边大家将日趋讲解在 CoreData
中展开增删改查的法门。

iOS数据存款和储蓄除了SQLite,FMDB,归档之外,项目中提到最多的正是CoreData.CoreData底层数据存款和储蓄也是SQLite,作为苹果官方支持的类似OTiguanM的框架,绝对于直接操作SQLite而言,CoreData至少裁减了五分之三~十分八的代码量.

</br>

核心的增加和删除改查

CoreData相比较SQLite尤其面向对象,对于一些数据查询,更新,建表等进度不要求过分关切,关怀首要在Model层面.CoreData相比较其余数据库的优势:
① 对象一致性,Model改变之后全局统一,保持对象关系里面包车型大巴等同性.

属性的机动验证,CoreData中实体对象,能够安装插入规则,使属性值在可承受的范围.

实体对象懒加载,CoreData中的关联对象,并不是在赢得实体的时候就从数据库加载至内部存款和储蓄器中,而是在使用进程中才从数据中展开加载.
④ 版本迁移,相对于SQLite而言,CoreData完结版本迁移的法子大致高效.
⑤ 复杂查询,对于复杂的SQL语句,能够经过NSPredicate读取对象的繁杂查询.


安排条目

先来看一下插入条指标情势,在插入此前,大家须要先创建要插入的数目, 使用
NSEntityDesctiption 类的
+ (__kindof NSManagedObject *)insertNewObjectForEntityForName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context;
方法来创立一个新的 NSManagedObject 对象,入参分别是 entityName
managedObjectContextentityName
约等于实体类的名字,例如,笔者要插入一条新的 Student 字段,entityName
就是 @”Student”;

context
NSManagedObjectContext目的,新增的实体类对象会添加到对应的 context
上下文对象中。这么些主意重返的是三个 NSManagedObject
实例,能够依照具体景况转换到相应的子类:

Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context];

student.studentName = @"小明";
student.studentId = 1;
student.studentAge = 20;

NSError *error;
[self.context save:&error];

调用 save 方法时,能够流传二个 NSError
的指针,假使数额保存出错的话,错误音信会保留到 error 里,这也是
Objective-C 里经常处理错误的法子。

基础知识

项目中一旦初步就须求动用CoreData,建立的时候能够勾选Use Core Data选项:

澳门威尼斯人网址 1

FlyElephant

假如第三次没有遗漏了Core
Data选项,或然项目中途必要运用CoreData,成立新的Data Model即可.

澳门威尼斯人网址 2

FlyElephant.png

开创的目的模型类型是NSManagedObjectModel托管类型的,3个托管对象模型关联三个模型文件(.xcdatamodeld),存款和储蓄着数据库的多少结构.

始建实体对象Order,添加订单号和订单名称多个脾性:

澳门威尼斯人网址 3

FlyElephant.png

能够成立Order的对象,创建步骤如下:

澳门威尼斯人网址 4

Paste_Image.png

选料要求创建的实体对象:

澳门威尼斯人网址 5

FlyElephant.png

享有创立的实体对象都以NSManagedObject的子类,对象CoreData中的Entity.

如若大家想对Order表实行例行则查询,更新,删除操作,会涉嫌到多个主要的类NSManagedObjectContext对象上下文,NSPersistentStoreCoordinator持久化协调器,负责Context和仓库储存之间的关系.实际执行进度如下:

澳门威尼斯人网址 6

FlyElephant.jpg

事实上本身想写那篇文章很久了,因为本身做的iOS开发 ,对数据这一块有那极高的必要.所以一些须求的存款和储蓄数据的利用,我们都有必不可少熟稔用法.在在此以前本人的简书中作者也是写过数额持久化,不过小编以为那一篇是不够完整的,全部小编把”增加和删除改查”那么些话题单独拿出去说一下. 明日首要说五个方面的增加和删除改查,分别是数组,字典,SQLite数据库,CoreData数据.

</br>

询问条目

从数据库中询问数据,会用到四个类:NSFetchRequestNSPredicateNSSortDescriptor,分别说一下那四个类的效用:

  • NSFetchRequest — fetchRequest 代表了一条查询请求,约等于 SQL 中的
    SELECT 语句
  • NSPredicate — predicate
    翻译过来是谓词的情趣,它可以钦点一些查询条件,也就是 SQL 中的 WHERE
    子句,有关 NSPredicate 的用法,能够看本身事先写过的一篇小说:动用
    NSPredicate
    进行数据库查询
  • NSSortDescriptor — sortDescriptor 是用来钦赐排序规则的,也便是 SQL
    中的 O奔驰G级DEEscort BY 子句

NSFetchRequest 中有七个属性
predicatesortDescriptors,正是用来钦赐询问的界定条件的。当中
sortDescriptors 是一个 NSSortDescriptor
的数组,也正是足以给二个询问内定多少个排序规则,那几个排序规则的优先级就是它们在数组中的地方,数组前边的预先级会比后边的高。除此之外,NSFetchRequest
还有下边这个属性

  • fetchLimit — 钦定结果集中数据的最大条文数,约等于 SQL 中的 LIMIT
    子句
  • fetchOffset — 钦命询问的偏移量,默认为 0
  • fetchBatchSize —
    钦赐批处理查询的尺寸,设置了那一个个性后,查询的结果集会分批重返
  • entityName/entity — 钦定询问的数据表,也便是 SQL 中的 FROM 语句
  • propertiesToGroupBy — 内定分组规则,约等于 SQL 中的 GROUP BY 子句
  • propertiesToFetch — 钦赐要查询的字段,暗中认可会查询全数字段

配置好 NSFetchRequest 对象后,必要调用 NSManagedObjectContext
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error;
来执行查询,重返的数组就是询问出的结果集。

Xcode 中预置了用来创制 fetchRequest 的code
snippet,键入fetch,就会现出相应的唤起:

./fetchrequest-w528

创办出来的代码是那样子的:

./fetchrequest2-w685

大多常用到的代码都在那边了。当然我们也得以团结来手写出来,上面正是二个最不难易行的查询语句:

NSFetchRequest *fetchRequest = [Student fetchRequest]; // 自动创建的 NSManagedObject 子类里会生成相应的 fetchRequest 方法
    // 也可以使用这种方式:[NSFetchRequest fetchRequestWithEntityName:@"Student"];

fetchRequest.predicate = [NSPredicate predicateWithFormat:@"studentAge > %@", @(20)];

NSArray<NSSortDescriptor *> *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"studentName" ascending:YES]];

fetchRequest.sortDescriptors = sortDescriptors;
// 
NSArray<Student *> *students = [self.context executeFetchRequest:fetchRequest error:nil];

增加和删除改查

丰盛100条的订单数量:
<pre><code>for i in 1...100 { let context:NSManagedObjectContext = CoreDataManager.sharedManager.mainQueueContext let order:Order = NSEntityDescription.insertNewObject(forEntityName: "Order", into: context) as! Order order.orderName = "台湾小零食--\(i)" order.orderNumber = Int32(i) if context.hasChanges { do { print("保存成功") try context.save() } catch { let nserror = error as NSError fatalError("Unresolved error \(nserror), \(nserror.userInfo)") } } }</code></pre>

查询插入的数量:

澳门威尼斯人网址 7

FlyElephant.png

<pre><code>Order.findAllOrders()</code></pre>
Order表中查询当地全数数据:
<pre><code>` static func findAllOrders() {

    let context:NSManagedObjectContext = CoreDataManager.sharedManager.mainQueueContext

    let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Order")

    let sortDescriptor = NSSortDescriptor.init(key: "orderNumber", ascending: true)

    fetchRequest.sortDescriptors = [sortDescriptor]

    do {
        let searchResults = try context.fetch(fetchRequest)
        if searchResults.count > 0 {

            for i in 0..<searchResults.count {
                let order:Order = searchResults[i] as! Order
                print("FlyElephant-订单编号:\(order.orderNumber)---订单名称:\(order.orderName!)")
            }
        } else {

        }
    } catch  {
        print(error)
    }

}`</code></pre>

数量更新,依照订单标号更新对应的数据:
<pre><code>` let number:Int = 30

    let order:Order? = Order.findOrderByID(id: number)

    if order != nil {
        print("订单号:\(number)的订单名称:\(order?.orderName)")

        order?.orderName = "FlyElephant\(number)_update"
        let context:NSManagedObjectContext = CoreDataManager.sharedManager.mainQueueContext

        if context.hasChanges {
            do {
                print("FlyElephant更新成功")
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }

    }`</code></pre>

Order中依据OrderNumber获取相应的Order数据:
<pre><code>` static func findOrderByID(id:Int) -> Order?
{

    let context:NSManagedObjectContext = CoreDataManager.sharedManager.mainQueueContext

    let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Order")

    let predicate = NSPredicate.init(format: " orderNumber = %@", "\(id)")
    fetchRequest.predicate = predicate

    do {
        let searchResults = try context.fetch(fetchRequest)
        if searchResults.count > 0 {
            let order:Order = searchResults[0] as! Order
            return order
        } else {
            return nil
        }
    } catch  {
        print(error)
    }

    return nil
}`</code></pre>

履新之后,执行查询操作,展现如下:

澳门威尼斯人网址 8

Paste_Image.png

依照orderNumer查询order,删除相应的订单:
<pre><code>` let number:Int = 80

    let order:Order? = Order.findOrderByID(id: number)

    if order != nil {
        print("FlyElephant订单号:\(number)的订单名称:\(order?.orderName)")

        let context:NSManagedObjectContext = CoreDataManager.sharedManager.mainQueueContext

        context.delete(order!)

        if context.hasChanges {
            do {
                print("\(number)删除成功")
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }`</code></pre>

澳门威尼斯人网址 9

Paste_Image.png

CoreDataManager是对CoreData的着力封装,代码如下:
<pre><code>`class CoreDataManager {

// MARK: 初始化

static let sharedManager = CoreDataManager()
static let applicationDocumentsDirectoryName = "com.coredata.www"
static let mainStoreFileName = "FECoreData.sqlite"
static let errorDomain = "CoreDataManager"

lazy var managedObjectModel: NSManagedObjectModel = {
    // 对应存储的模型FECoreData.xcdatamodeld
    let modelURL = Bundle.main.url(forResource: "FECoreData", withExtension: "momd")!
    return NSManagedObjectModel(contentsOf: modelURL)!
}()

// 持久化协调器

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {

    let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

    do {
        // 自动升级选项设置
        let options = [
            NSMigratePersistentStoresAutomaticallyOption: true,
            NSInferMappingModelAutomaticallyOption: true
        ]

        try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: self.storeURL as URL, options: options)
    }
    catch {
        fatalError("FlyElephant持久化存储错误: \(error).")
    }

    return persistentStoreCoordinator
}()


lazy var mainQueueContext: NSManagedObjectContext = {

    let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    moc.persistentStoreCoordinator = self.persistentStoreCoordinator

    // 避免多线程中出现问题,如果有属性和内存中都发生了改变,以内存中的改变为主
    moc.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

    return moc
}()


/// CoreData 文件存储目录
//
lazy var applicationSupportDirectory: URL = {

    let fileManager = FileManager.default
    var supportDirectory:URL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).last!

    var saveUrl:URL = supportDirectory.appendingPathComponent(applicationDocumentsDirectoryName)

    if fileManager.fileExists(atPath: saveUrl.path) == false {
        let path = saveUrl.path
        print("文件存储路径:\(path)")
        do {

            try fileManager.createDirectory(atPath: path, withIntermediateDirectories:true, attributes:nil)
        }
        catch {
            fatalError("FlyElephant文件存储目录创建失败: \(path).")
        }
    }

    return saveUrl
}()


lazy var storeURL: URL = {
    return self.applicationSupportDirectory.appendingPathComponent(mainStoreFileName)
    }()


// 创建私有CoreData存储线程
func newPrivateQueueContextWithNewPSC() throws -> NSManagedObjectContext {

    // 子线程中创建新的持久化协调器
    //
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: CoreDataManager.sharedManager.managedObjectModel)

    try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: CoreDataManager.sharedManager.storeURL as URL, options: nil)

    let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)

    context.performAndWait() {

        context.persistentStoreCoordinator = coordinator

        context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

    }

    return context
}

}
`</code></pre>

数组


删除条目

简单易行的删除条目仍然比较简单的,在上一步里询问出来后,只需调用
NSManagedObjectContext
- (void)deleteObject:(NSManagedObject *)object;
方法来删除贰个条款。例如,将上边查询出来的 students
全体删减,能够如此写:

for (Student *student in students) {
    [self.context deleteObject:student];
}  
[self.context save:nil]; // 最后不要忘了调用 save 使操作生效。

先是说一下数组的增加和删除改查.数组协会是大家做开发中平常应用的一种结构.然后看一下数组的”增加和删除改查”是何许进展的吧.当然了,我们要事项说雅培(Abbott)些,正是数组分为可变数组,和不足变数组.不可变数组是没有增加和删除改查的,全数大家只会对可变数组的增加和删除改查举办钻探.当然了.字典也是均等的.

    //使用便利构造器创建一个可变数组
    NSMutableArray *mtuArray = [NSMutableArray array];

    //增
    //给数组增加一些元素
    [mtuArray addObject:@"栋哥"];

    //给数组中添加一个数组
    [mtuArray addObjectsFromArray:@[@"强哥",@"其弟"]];


    //改
    //根据下标修改某个值
    mtuArray[1] = @"萌神";

    //查
    if ([mtuArray containsObject:@"栋哥"]) {

        NSLog(@"存在栋哥!");

    }else{

        NSLog(@"栋哥不知道去哪了?");

    }


    //删
    //删除数组某一个元素
    [mtuArray removeObject:@"栋哥"];

    //根据下标删除数组的某一个元素
    [mtuArray removeObjectAtIndex:1];

    //删除所有的元素
    [mtuArray removeAllObjects];

    //删除最后一个元素
    [mtuArray removeLastObject];

</br>

履新条目

或然在查询出的 students
数组的根底上,要是要翻新里面包车型大巴字段,能够遍历那些数组,依次修改数组里成分的字段:

for (Student *student in students) {
        student.studentName = @"newName";
    }

[self.context save:nil];

字典


增加和删除改查进阶

字典是基于键值对存款和储蓄数据的,当然了字典和数组的”增加和删除改查”相比较相近,不可变字典是从未有过”增加和删除改查”的职能的.唯有可变字典存在”增加和删除改查”;那我们看一下字典中的增加和删除改查是怎么着进展的

//根据便利构造器创建一个可变字典
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];

    //增
    //添加单个键值对
    [dic setObject:@"栋哥" forKey:@"菜比"];

    //添加一个不可变字典
    [dic setDictionary:@{@"大神":@"其弟"}];

    //删
    //删除某一个键值对
    [dic removeObjectForKey:@"大神"];

    //删除字典中的所有元素
    [dic removeAllObjects];

    //改
    //改变某个键的值
    dic[@"菜比"] = @"面面";


    //查
    //注意:字典遍历一遍是在遍历所有的键,我们需要比对键的值来查找某个元素
    for (NSString *key in [dic allKeys]) {

        if ([dic[key] isEqualToString:@"栋哥"]) {

            NSLog(@"栋哥存在了!");

        }else{
            NSLog(@"栋哥不存在!");
        }
    }

</br>

批量布署

简简单单的批量安排和插入单条数据一致,只是在颇具的数量都插入唯有才调用
[context save]; 来保存。上边是简简单单的以身作则代码:

for (NSUInteger i = 0; i < 1000; i++) {
    Student *newStudent = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.context];

    int16_t stuId = arc4random_uniform(9999);    
    newStudent.studentName = [NSString stringWithFormat:@"student-%d", stuId];
    newStudent.studentId = stuId;
    newStudent.studentAge = arc4random_uniform(10) + 10;
}

[self.context save:nil];

SQLite数据库


批量翻新

那边讲的批量翻新方式,用到的是集聚类型中的 KVC 特性。那是什么样啊?就是在
NSArray 那样的集聚类型里,能够调用它的 [setValue: forKeyPath:]
方法来更新那一个数组中保有因素所对应的 keypath。例如想要将方面查询出来的
students 数组里全部因素的 studentName 属性都修改成
@"anotherName",就可以那样来写:

[students setValue:@"anotherName" forKeyPath:@"studentName"];

除外那种批量创新的章程,还有上面将要讲的 NSBatchUpdateRequest
也足以开始展览批量更新,不妨跟着往下看。

SQLite数据库是iOS内嵌的三个数据库,合适大型数据的读写,主要用以地点一些音讯的存款和储蓄,SQLite数据库选用表结构来储存数据的.我们想在Xcode中应用SQLite数据库,大家就要起先入大家的库.

</br>

NSBatchUpdateRequest 批量更新

NSBatchUpdateRequest 是在 iOS 8, macOS 10.10 之后新增进的
API,它是专程用来进行批量翻新的。因为用地方那种办法批量创新的话,会存在三个题材,正是创新前需求将要翻新的数目,查询出来,加载到内部存款和储蓄器中;那在数据量非常大的时候,借使说要立异八万条数据,就相比麻烦了,因为对此手机这种内部存款和储蓄器相比小的装置,直接加载这么多多少到内存里显著是不容许的。化解办法正是历次只询问出读取一小部分数额到内部存款和储蓄器中,然后对其开始展览翻新,更新完事后,再次创下新下一批,就像此分批来拍卖。但那显著不是便捷的消除方案。

于是乎就有了 NSBatchUpdateRequest 这个API。它的办事原理是不加载到内部存储器里,而是径直对地方数据库中数据开始展览创新。那就防止了内部存款和储蓄器不足的题材;但同时,由于是直接更新数据库,所以内存中的
NSManagedObjectContext 不会精晓数据库的浮动,消除办法是调用
NSManagedObjectContext
+ (void)mergeChangesFromRemoteContextSave:(NSDictionary*)changeNotificationData intoContexts:(NSArray<NSManagedObjectContext*> *)contexts;方法来告诉
context,有怎么样数据更新了。

上面来看一下 NSBatchUpdateRequest 的用法。

  1. 创建

    // 根据 entity 创建
    NSBatchUpdateRequest *updateRequest = [[NSBatchRequest alloc] initWithEntity:[Student entity]];
    // 根据 entityName 创建
    NSBatchUpdateRequest *updateRequest = [[NSBatchUpdateRequest alloc] initWithEntityName:@"Student"];
    
  2. predicate

    NSBatchUpdateRequest
    predicate用来钦命更新标准,例如那里钦命更新 studentAge 等于 20
    的学员

    updateRequest.predicate = [NSPredicate predicateWithFormat:@"studentAge == %@", @(20)];
    
  3. propertiesToUpdate

    propertiesToUpdate
    属性是贰个字典,用它来钦赐须求立异的字段,字典里的 key
    正是要更新的字段名,value 便是要设置的新值。因为 Objective-C
    字典里只可以存款和储蓄对象类型,所以若是字段基本数据类型的来说,须要转移成
    NSNumber 对象。

    updateRequest.propertiesToUpdate = @{@"studentName" : @"anotherName"};
    
  4. resultType

    resultType 属性是 NSBatchUpdateRequestResultType
    类型的枚举,用来钦命重返的数据类型。那几个枚举有多少个成员:

    • NSStatusOnlyResultType — 重返 BOOL 结果,表示更新是不是履行成功
    • NSUpdatedObjectIDsResultType — 重返更新成功的靶子的 ID,是
      NSArray<NSManagedObjectID *> * 类型。
    • NSUpdatedObjectsCountResultType
      重返更新成功数据的总和,是数字类型

    一般我们将其钦赐为 NSUpdatedObjectIDsResultType

    updateRequest.resultType = NSUpdatedObjectIDsResultType;
    
  5. executeRequest

    配置完 NSBatchUpdateRequest 对象后,就能够经过 context 的
    - (nullable __kindof NSPersistentStoreResult *)executeRequest:(NSPersistentStoreRequest*)request error:(NSError **)error;
    方法来推行批量翻新了:

    NSBatchUpdateResult *updateResult = [self.context executeRequest:updateRequest error:&error];
    NSArray<NSManagedObjectID *> *updatedObjectIDs = updateResult.result;
    

    executeRequest 方法重回的是 NSBatchUpdateResult 对象,里面有一个
    id result 属性,它的切实项目正是近日通过枚举成员内定的类型。

  6. mergeChanges

    底层数据更新之后,以往要布告内部存款和储蓄器中的 context 了,调用 context
    mergeChanges
    方法,第③个参数是个字典,钦命要联合的数据类型(是立异依旧删除、插入等);第①个参数就是context 数组,钦命要统一到怎样 context 中去。

    NSDictionary *updatedDict = @{NSUpdatedObjectsKey : updatedObjectIDs};
        [NSManagedObjectContext mergeChangesFromRemoteContextSave:updatedDict intoContexts:@[self.context]];
    

到那里,批量创新的操作就讲完了,下边来看 NSBatchDeleteRequest
批量删除。

导完了今后,大家第②要有3个Model的沙盘,那里笔者就以Student 为类名来成立二个简单的模板.

</br>

NSBatchDeleteRequest 批量删除

NSBatchDeleteRequest 的用法和 NSBatchUpdateRequest 很一般,区其余是
NSBatchDeleteRequest 须要钦点 fetchRequest 属性来拓展删除;而且它是
iOS 9 才添加进去的,和 NSBatchUpdateRequest
的适用范围不雷同,下边看一下示范代码:

NSFetchRequest *deleteFetch = [Student fetchRequest];

deleteFetch.predicate = [NSPredicate predicateWithFormat:@"studentAge == %@", @(20)];

NSBatchDeleteRequest *deleteRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:deleteFetch];
deleteRequest.resultType = NSBatchDeleteResultTypeObjectIDs;

NSBatchDeleteResult *deleteResult = [self.context executeRequest:deleteRequest error:nil];
NSArray<NSManagedObjectID *> *deletedObjectIDs = deleteResult.result;

NSDictionary *deletedDict = @{NSDeletedObjectsKey : deletedObjectIDs};
[NSManagedObjectContext mergeChangesFromRemoteContextSave:deletedDict intoContexts:@[self.context]];

好了,CoreData 中的增加和删除改查就讲完了,下篇小说将会介绍 CoreData Model
中的 relationships 完毕多表关联的用法。

我们在Student.h文件中是这么写的.
#import <Foundation/Foundation.h>

@interface Student : NSObject

@property(nonatomic,strong)NSString *name;

@property(nonatomic,strong)NSString *gender;

@property(nonatomic,assign)int Stu_ID;

@property(nonatomic,assign)int age;

-(instancetype)initWithName:(NSString *)name
                     gender:(NSString *)gender
                      stuID:(int)stuID
                        age:(int)age;
@end
Student.m是那样写的,都以很简单的
-(instancetype)initWithName:(NSString *)name
                     gender:(NSString *)gender
                      stuID:(int)stuID
                        age:(int)age{

    if (self = [super init]) {

        _age = age;

        _name = name;

        _gender = gender;

        _Stu_ID = stuID;

    }

    return self;

}


-(void)setValue:(id)value forUndefinedKey:(NSString *)key{

}

- (NSString *)description
{
    return [NSString stringWithFormat:@"%@", _name];
}


@end

</br>

模板做好了,上边大家就对SQLite 数据做一些调用了,在调整从前,先把有个别常用的SQLite语句,也是SQLite数据库的增加和删除改查作用

</br>

瞩目 :SQLite语句相比易于失误,所以本身提议大家尽量全都复制黏贴,不要用手敲SQLite 语句!!

//创建表

CREATE TABLE "Class43" ("Stu_ID" INTEGER PRIMARY KEY NOT NULL UNIQUE, "name" TEXT NOT NULL, "gender" TEXT NOT NULL DEFAULT M, "age" INTEGER NOT NULL);

//添加

//方式1(字段和值一一对应(局部添加))
INSERT INTO Class43(Stu_ID,name,gender,age) VALUES (2,'栋哥','男',18)

//方式2 (整体赋值)(插入数据的时候需要和表里面的顺序一样)
INSERT INTO Class43 VALUES (3,'栋哥','男',17)


//修改

//方式1整体修改(没有指定指定关键字,则修改全部)
UPDATE Class43 SET age = 18

//方式2 局部修改
UPDATE Class43 SET age = 18  WHERE  name ='骚栋'


// 查询

//方式1查询全部
SELECT * FROM Class43 

//方式2 局部查询
SELECT * FROM Class43  WHERE name = '栋哥'


//删除

//方式1 局部变量
DELETE FROM Class43 WHERE Stu_ID = 3

//方式2 全局变量
DELETE FROM Class43 

//删除表
DROP TABLE Class43


//查找
select * from users order by id limit 1 offset 0

offset代表从第几条记录“之后“开始查询,limit表明查询多少条结果

</b>

此间大家成立三个伪单例来存款和储蓄大家的SQLite数据库.

在DataBase.h文件我们做导入sqlite3库 , 成立单例的方法表明和增加和删除改查的法子证明.
#import <Foundation/Foundation.h>

#import <sqlite3.h>

@class Student;

@interface DataBase : NSObject

//创建单例
+(instancetype)shareDataBase;

//打开数据库
-(void)openDB;

//关闭数据库
-(void)closeDB;

//添加
-(void)insertStudent:(Student *)student;

//删除
-(void)deleteStudent:(int)studentID;

//修改
-(void)upDateStudentWithGender:(NSString *)gender andStuID:(int)stu_id;

//查询全部
-(NSArray <Student *> *)selectAllStudent;

//查询单个学生
-(Student *)selectStudent:(int)Stu_ID;


@end

</br>

在DataBase.h文件大家对创设单例的主意评释和增加和删除改查的主意开始展览达成.

</br>

引入Model文件, 达成单例初步化方法.
#import "DataBase.h"

#import "Student.h"

@implementation DataBase

static DataBase *dataBase = nil;

+(instancetype)shareDataBase{

    //加锁(多线程)
    @synchronized(self) {

        if (nil == dataBase) {

            dataBase = [[DataBase alloc]init];

            //打开数据库
            [dataBase openDB];
        }

    }

    return dataBase;

}
到现在先把SQL数据库定义在静态区.
static sqlite3 *db =nil;

</br>

笔者们无论做增加和删除改查什么操作,都要先打开数据库,然后再做相应的操作,
打开数据库方法解释 :就算数据库不为空,大家就不供给重新成立直接回到,当数据库为空的时候,大家想先找到沙盒对应的门径,然后成立数据库,最终在数据库中创设表格.
//打开数据库
-(void)openDB{

    //如果数据库已经打开,则不需要执行后面的操作
    if (db != nil) {

        return;

    }


    //创建保存数据库的路径
    NSString *docmsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

    docmsPath = [docmsPath stringByAppendingString:@"/LOClass.sqlite"];

    NSLog(@"%@",docmsPath);
    //打开数据库(如果该数据库存在,则直接打开,否则,会自动创建一个再打开)
   int result =  sqlite3_open([docmsPath UTF8String], &db);

    if (result == SQLITE_OK) {

        NSLog(@"数据库成功打开");

        //建表
        //1.准备SQL语句
        NSString *sql = @"CREATE TABLE Class43 (Stu_ID INTEGER PRIMARY KEY NOT NULL UNIQUE, name TEXT NOT NULL, gender TEXT NOT NULL DEFAULT M, age INTEGER NOT NULL);";

        //2.执行语句
        sqlite3_exec(db, [sql UTF8String], nil, nil, nil);

    }else{

        NSLog(@"%d",result);
    }

}

</br>

当大家操作完对应的操作后大家需求关闭数据库,代码如下
闭馆数据库方法解释 : 关闭数据库的时候,我们须要调用sqlite3_close()方法,然后把我们的数量库置为nil,那样数据库就完全关闭了.
//关闭数据库
-(void)closeDB{

    int result = sqlite3_close(db);

    //关闭数据库的时候,将db置为空,是因为打开数据库的时候,我们需要使用nil做判断.
    db = nil;

    if (result == SQLITE_OK) {

        NSLog(@"数据库关闭成功!");

    }else{

        NSLog(@"数据库关闭失败:%d",result);

    }

}

</br>

SQL数据库扩充效果
扩大方法的表明: 首先我们要求开辟数据库,然后创设跟随指针,跟随指针的效能能够领略为绑定叁个整机Model数据到要履行的SQLite语句上,然后再对那几个Model进行操作.然后创设SQLite语句并运转,当大家的SQLi特语句执行成功的时候,那时候跟随指针就绑定Model ,然后单步执行.最终要释放到跟随指针.
/添加
-(void)insertStudent:(Student *)student{

    //1.打开数据库
    [self openDB];

    //2.创建跟随指针
    sqlite3_stmt *stmt = nil;

    //3.准备sql语句
    NSString *sql =@"INSERT INTO Class43(Stu_ID,name,gender,age) VALUES (?,?,?,?)";

    //4.验证sql语句的正确性
    int result = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, nil);

    //5.判断 并且绑定
    if (result == SQLITE_OK) {

        NSLog(@"数据库添加成功");

        //一旦sql语句没有问题就开始绑定数据,替换问号
        //参数:(1)跟随指针 (2)问号的顺序呢(从1开始) (3)要绑定的值
        sqlite3_bind_int(stmt, 1, student.Stu_ID);

        sqlite3_bind_text(stmt, 2, [student.name UTF8String], -1, nil);

        sqlite3_bind_text(stmt, 3, [student.gender UTF8String], -1, nil);

        sqlite3_bind_int(stmt, 4, student.age);

        //6.单步执行
        sqlite3_step(stmt);

    }else{

        NSLog(@"数据库添加失败:%d",result);

    }


    //释放跟随指针占用的内存
    sqlite3_finalize(stmt);


}

</br>

SQL数据库删除功用
去除方法的分解: 首先大家供给打开数据库,然后创制跟随指针,然后创设删除的SQL语句并执行,当执行成功以往,大家就会让随行指针绑定大家的删减条件,然后单步执行. 执行到位以后,大家需求手动释放跟随指针.
//删除
-(void)deleteStudent:(int)studentID{

    [self openDB];

    //创建跟随指针
    sqlite3_stmt *stmt = nil;

    //准备sql语句
    NSString *sql = @"DELETE FROM Class43 WHERE Stu_ID = ?";

    //验证正确与否
    int result = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, nil);

    //开始删除
    if (result == SQLITE_OK) {

        //开始绑定
        sqlite3_bind_int(stmt, 1, studentID);


        //单步执行
        sqlite3_step(stmt);

        NSLog(@"删除成功");

    }else{

        NSLog(@"删除失败");

    }

    //释放
    sqlite3_finalize(stmt);

}

</br>

SQL数据库修改效率
修章的解释: 首先我们需求开辟数据库,然后更创造跟随指针,创立跟随指针完结以往,大家须求成立咱们的SQL语句并实施,假使执行成功,大家就让我们的追随指针绑定我们的筛选标准,然后单步执行,最终获释大家的尾随指针.
//修改
-(void)upDateStudentWithGender:(NSString *)gender andStuID:(int)stu_id{


    [self openDB];

    sqlite3_stmt *stmt = nil;

    NSString *sql = @"UPDATE Class43 SET gender = ?  WHERE  Stu_ID = ?";

    int result = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, nil);

    if (result == SQLITE_OK) {

        NSLog(@"修改成功");

        sqlite3_bind_int(stmt, 2, stu_id);

        sqlite3_bind_text(stmt, 1, [gender UTF8String], -1, nil);

        sqlite3_step(stmt);


    }else{

        NSLog(@"修改失败");

    }

    //释放
    sqlite3_finalize(stmt);
}

</br>

SQL数据库查询任何表格效率
询问任何格局的解释:首先打开大家的数据库,创造跟随指针,创制完毕未来,我们就成立我们的SQL语句并执行.假使执行成功的话,大家就利用while循环反复执行大家的语句,根据sql语句将寻找到的符合条件的值取出来并绑定我们的追随指针,然后把询问到的数量存到数组中,最终不管是否查询成功,都要释放大家的随从指针.
-(NSArray<Student *> *)selectAllStudent{

    [self openDB];

    sqlite3_stmt *stmt = nil;

    NSString *sql = @"SELECT * FROM Class43";

    int result = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, nil);

    if (result == SQLITE_OK) {

        NSLog(@"查询成功!");

        //创建可变数组用来存放查询到的学生
        NSMutableArray *array = [NSMutableArray array];

        while (sqlite3_step(stmt) == SQLITE_ROW) {

            //根据sql语句将搜索到的符合条件的值取出来(0 代表数据库表的第一列);
            int stu_id = sqlite3_column_int(stmt, 0);

            NSString *name =[NSString stringWithUTF8String: (const char *)sqlite3_column_text(stmt, 1)];

            NSString *gender = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 2)];

            int age = sqlite3_column_int(stmt, 3);

            //将取出来的信息赋值给学生的model
            Student *student = [[Student alloc]initWithName:name gender:gender stuID:stu_id age:age];

            [array addObject:student];


        }


        sqlite3_finalize(stmt);

        return array;

    }else{

        NSLog(@"查询失败!");


        sqlite3_finalize(stmt);

        return nil;


    }


}

</br>

SQL数据库查询单个表格效能
询问单个方法的分解:首先打开大家的数据库,创立跟随指针,创设实现之后,大家就创办大家的SQL语句并执行.若是实施成功的话,大家就应用while循环反复执行大家的言辞,依照sql语句将寻找到的符合条件的值取出来并绑定大家的随行指针,然后把询问到的数额存到对应Model中,最终不管是不是查询成功,都要自由大家的追随指针.
//查询单个学生
-(Student *)selectStudent:(int)Stu_ID{

    //打开数据库
    [self openDB];

    //创建跟随指针
    sqlite3_stmt *stmt = nil;

    //准备sql语句
    NSString *sql = @"SELECT * FROM Class43  WHERE Stu_ID = ?";

    //验证
    int  result = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, nil);

    if (result == SQLITE_OK) {

        NSLog(@"查询成功!");

        //绑定
        sqlite3_bind_int(stmt, 1, Stu_ID);

        Student *stu =[Student new];

        //执行
        while (sqlite3_step(stmt) == SQLITE_ROW) {

            stu.Stu_ID = sqlite3_column_int(stmt, 0);

            stu.name = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 1)];

            stu.gender = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 2)];

            stu.age = sqlite3_column_int(stmt, 3);

        }

        sqlite3_finalize(stmt);

        return stu;

    }else{

        NSLog(@"查询失败:%d",result);

        sqlite3_finalize(stmt);

        return nil;

    }

}

</br>

CoreData数据库


相比于SQLite数据库, CoreData数据库就先相对的总结了诸多,CoreData的贯彻原理你能够想象是github的公文物管理理一样.您本地是内部存款和储蓄器,github的服务器是沙盒,你在内存操作完事后就手动传到沙盒中展开本地化保存.其实 CoreData数据库是对SQLite数据库的封装.而且CoreData援救可视化建立模型.更是大大缩小了大家的代码量,以后大家就看一下CoreData的达成步骤以及增加和删除改查效能.

</br>

创建工程的时候,我们要求手动添加数据库
此刻,Xcode会自动协理我们在AppDelegate里不熟悉成多少个附加的属性.属性的表达如下
//被管理对象上下文,相当于一个临时数据库,我们存储或者查询都是通过这个对象来进行的.
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

//被管理对象模型,可以简单的理解为可视化建模文件.我们在可视化建模中是Entity,自动生成Model,就是这个对象.方便让文件存储助理进行管理.
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;

//文件存储助理,他是CoreData的核心.他负责连接所有的模块,包括真实的存储文件.
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

//将我们在内存中的操作进行持久化.
- (void)saveContext;
//获取真实文件的路径.
- (NSURL *)applicationDocumentsDirectory;
那里笔者对地方的Core做了有个别回顾的总计
/*
 1.CoreData 是苹果公司封装的数据持久化框架.在iOS3.0中开始开放.
 2.它允许用户按照实体-属性-值模型组织数据,并以二进制,XML,或者sqlite数据文件的格式进行持久化.

 CoreData的优势
 1.他是苹果公司原生态的产品.
 2.他可以节省代码量,大概是30%~70%.
 3.它支持可视化建模.
 4.CoreData 支持数据库版本升级.

 可以通过Editor下的菜单进行生成模型,将Entity生成Model.
 在其过程中有一个选项,勾选,生成的是标量,不勾选,生成的是通量.

 */
相对于SQLite中的代码建立模型,CoreData特别简洁.

</br>

如图添加1个Model

</br>

点击 Create 生成3个Model

</br>

慎选生成的门道和生成的Model ,最终大家须求做标量和通量的选用.

</br>

在说”增删改查”此前,笔者要说三个代码块 ,这几个代码块的输入代码是 *** fetch – Core Data Fetch*** 代码块如下,那就是大家要从沙盒中搬到内部存款和储蓄器的数量,当然了,大家必要做一些谓词筛选等,下边包车型客车增加和删除改查中会用到.查询到的结果就在fetchedObjects那些数组中贮存着.

 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"<#Entity name#>" inManagedObjectContext:<#context#>];
    [fetchRequest setEntity:entity];
    // Specify criteria for filtering which objects to fetch
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"<#format string#>", <#arguments#>];
    [fetchRequest setPredicate:predicate];
    // Specify how the fetched objects should be sorted
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"<#key#>"
                                                                   ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];

    NSError *error = nil;
    NSArray *fetchedObjects = [<#context#> executeFetchRequest:fetchRequest error:&error];
    if (fetchedObjects == nil) {
        <#Error handling code#>
    }

</br>

本人是在ViewController做一些”增加和删除改查”的操作,首先大家须求证明七个属性,叁个是沟通上下文的对象是三个用于保存数据的数组,首先,大家会在ViewDidLoad进行初叶化一下.
#import "ViewController.h"

#import "AppDelegate.h"

#import "Student.h"

@interface ViewController ()

//创建一个上下文对象,用于处理所有与存储相关的请求.
@property(nonatomic,strong)NSManagedObjectContext *myContext;

//创建一个数组,用于存储数组的数据源.
@property(nonatomic,strong)NSMutableArray *allData;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //进行数据初始化
    self.allData = [ NSMutableArray array];

    AppDelegate *dele = [UIApplication sharedApplication].delegate;

    self.myContext = dele.managedObjectContext;

}

</br>

CoreData数据库增加功用

数据库扩展效用方法解释: 首先大家须求成立1个实体描述对象然后存到联系上下文对象中,给那些实体描述对象开始展览赋值. 再由NSManagedObjectContext对象开展地面化存款和储蓄.
-(void)addObject{

    //1.创建Student对象

    //创建一个实体描述对象
    NSEntityDescription *description = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:self.myContext];

    Student *stu = [[Student alloc]initWithEntity:description insertIntoManagedObjectContext:self.myContext];
    //给属性赋值

    stu.name = @"张三";

    stu.age = arc4random()%73+1;

    [self.allData addObject:stu];

    //本地化保存
    AppDelegate *dele = [UIApplication sharedApplication].delegate;

    [dele saveContext];


}

</br>

CoreData数据库删除效能

数据库删除功效方法解释: 删除只必要大家把地面包车型客车myContext对象中的实体化对象删除掉,然后再保存就行.
-(void)deleteObject{

    //获取当前代表的数据
    Student *stu = self.allData[1];

    //将临时数据库进行删除并进行本地持久化
    [self.myContext  deleteObject:stu];

    [self.myContext save:nil];

}

</br>

CoreData数据库修改功效

数据库修改作用方法解释: 首先我们需求把沙盒中的数据表格更新到大家的内部存储器对象myContext中去,然后修改实例化对象的值,然后保留到数组,中,最后在展开数量持久化操作.
 -(void)upDataObject{

    //先查询
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:self.myContext];
    [fetchRequest setEntity:entity];
    // Specify criteria for filtering which objects to fetch

    //  how the fetched objects should be sorted
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age"
                                                                   ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];

    NSError *error = nil;
    NSArray *fetchedObjects = [self.myContext executeFetchRequest:fetchRequest error:&error];
    if (fetchedObjects == nil) {


    }
    //修改对对应的数据
    Student *stu  = self.allData[1];
    stu.name = @"尼古拉斯-赵四";
    //更新数据源
    [self.allData removeAllObjects];
    [self.allData addObjectsFromArray:fetchedObjects];

    //将修改本地持久化
    [self.myContext save:nil];


}

</br>

CoreData数据库查询效用

数据库查询效率方法解释: 那里只做完全的询问,当大家要求查询某些数据的时候,大家就要先从国土中下载到内部存款和储蓄器中,然后保留到大家的数组中.在对数组实行遍历操作,查询我们的对象.
-(void)selectAllData{

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:self.myContext];
    [fetchRequest setEntity:entity];
    // Specify criteria for filtering which objects to fetch

    // Specify how the fetched objects should be sorted
    //排序条件
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age"
                                                                   ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];

    NSError *error = nil;
    NSArray *fetchedObjects = [self.myContext executeFetchRequest:fetchRequest error:&error];
    if (fetchedObjects == nil) {

        NSLog(@"两手空空,你让我拿什么飞天?");

    }

    //将查询到的数据添加到数据源
    [self.allData addObjectsFromArray:fetchedObjects];

}

</br>

用作”增加和删除改查”那四个操作,是大家程序员对数码最核心的操作,希望我们能够欣赏这篇,借使喜欢就点个赞呗 

相关文章