CoreDataについて

22342 ワード

技術スタックの第2部を理解する:Core Data

Core Data?


Framework
コアデータはデータベースではありません.フレームが大きい.

Overview


Use Core Data to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device.
コア・データを使用すると、永続的なデータをオフラインで使用し、単一のデバイス上のアプリケーションに元に戻す機能を追加できます.
Through Core Data’s Data Model editor, you define your data’s types and relationships, and generate respective class definitions. Core Data can then manage object instances at runtime to provide the following features.
コアデータのデータモデルエディタで、データのタイプと関係を定義し、各クラスの定義を生成します.
コア・データは、ランタイム・オブジェクト・インスタンスを管理し、次の機能を提供します.

Persistence


Core Data abstracts the details of mapping your objects to a store, making it easy to save data from Swift and Objective-C without administering a database directly.
コアデータは、オブジェクトをリポジトリにマッピングする詳細情報を抽象化するため、データベースを直接管理することなく、SWIFTおよびObjective-Cにデータを簡単に格納できます.
  • SQLiteとは?
  • SQL言語に基づいて作成されたデータベースがあります.これが方法の1つです.
    SQLiteは、モバイル環境に最適化されたデータベースです.
  • リレーショナル・データベースとは?
  • これは、キーと値の間の単純な関係を表化する非常に簡単な原則の電算情報データベースです.
    コアデータ機能の1つであるPersistenceは、リレーショナル・データベースSQLiteによってサポートされています.
    ただし、ここで注意したいのは、PersistenceはCore Data=DatabaseではなくCore Dataの機能の1つにすぎないことです.
    Persistence機能を使用することなくCore Dataを使用できます.Core Dataはデータベースではなく、データを維持するためのAPIではないことを覚えておいてください.
    これはアプリケーションのモデル層にすぎず、オブジェクトのグラフィックを管理するFrameworkです.

    Undo and Redo of Individual or Batched Changes


    Core Data’s undo manager tracks changes and can roll them back individually, in groups, or all at once, making it easy to add undo and redo support to your app.
    コア・データの取り消しマネージャは、変更を追跡し、個別、グループ、またはすべてにロールバックすることができるため、アプリケーションにデータを簡単に追加、削除できます.

    Background Data Tasks


    Perform potentially UI-blocking data tasks, like parsing JSON into objects, in the background. You can then cache or store the results to reduce server roundtrips.
    例えば、バックグラウンドでJSONオブジェクトをパーティション化するなど、UIブロックデータ操作を実行します.
    これにより、結果をキャッシュまたは保存することができ、サーバポーリング時間(往復遅延)を短縮できます.

    View Synchronization


    Core Data also helps keep your views and data synchronized by providing data sources for table and collection views.
    コア・データには、テーブル・ビューとコレクション・ビューのデータ・ソースも用意されており、ビューとデータの同期に役立ちます.

    Versioning and Migration


    Core Data includes mechanisms for versioning your data model and migrating user data as your app evolves.
    コア・データには、アプリケーション・バージョンのアップグレードに伴い、データモデルをバージョン化し、ユーザー・データを移行するメカニズムが含まれています.
    Core DataのEntityのInspectorからこのような画面が見えます.

    以上の3つのオプションは、それぞれの機能を提供します.
    Class Definition
  • コアデータから生成された管理対象サブクラスおよびプロセスまたは機能を編集する必要がない場合、
  • (これは機能ではなく特性)によって生成されたソースコードは、プロジェクトのソースリストに表示されません.
  • この場合に使用するオプション.そしてこの特徴のためです.
    let contact = Contact()
    以上のコードは返すことができます.
    Categort/Extension
  • 管理対象サブクラスに便利なメソッドまたはビジネスロジックを追加するには、
  • を選択します.
  • このオプションを使用すると、クラスファイルを完全に制御できます.
  • Manual/None
  • 管理対象サブクラスを編集してアクセス修飾子を変更し、より便利なメソッドまたはビジネスロジックを追加する
    このオプションを選択した場合、Core Dataはclassをサポートするファイルを生成しません.
  • Core Data Stack


    Core Data StackはCore Dataのコアです.
    Core Data Stackは、アプリケーションのモデル層の管理と維持を担当します.

    上図のようにNSManagedObjectModel NSManagedObjectContext NSPersistenStoreCoordinatorまだあります.NSPersistentContainerからなる.
    一つずつ見ます.

    NSManagedObjectModel


    Entityを説明するDatabase Skimaと見なすことができます.
    管理対象オブジェクトの構造を定義します.

    機能の一つのようです.

    NSPersistentStoerCoordinator


    永続ストレージは、管理対象モデルに関連付けられます.
    アップルの公式ドキュメントの説明
    A coordinator that uses the model to help contexts and persistent stores communicate.
    モデルを使用してcontextおよび永続リポジトリとの通信をサポートするコーディネータ.

    この図の真ん中にPersistent Store Coordinatorがあります.
    中間に接続の役割がある

    NSManagedObjectContext


    Transactionと言える
    管理対象オブジェクトの作成、保存、および取得.
    アップルの公式ドキュメントの説明
    An object space to manipulate and track changes to managed objects.
    変更オブジェクトの変更内容を操作および追跡するオブジェクト空間.

    NSPersistentContainer

  • CoreData Stackを表すすべての必須オブジェクトが含まれます.
  • この程度を確認してみましょう!コードで直接適用する内容を見てみましょう.

    Core Dataの使用

    static var shared: CoreDataWorker = CoreDataWorker()
        
        lazy var feedArrayContainer: NSPersistentContainer = {
            let container = NSPersistentContainer(name: "Model")
            container.loadPersistentStores(completionHandler: {
                (data, error) in
                if let error = error as NSError? {
                    fatalError("Error")
                }
            })
            return container
        }()
    これはCore Data Stackで説明した最上位レベルです.NSPerisistenContainerは、Core Data Stackを表すすべての必要なオブジェクトを含む.そこで、Core Data Stackを使用するために、このようにModelによって建てられたEntityが呼び出された.
    var feedContext: NSManagedObjectContext {
        return feedArrayContainer.viewContext
    }
    次のコードはNSManagedObjectContextにインポートされたコードです.
    NSManagedObjectContextは、管理対象オブジェクトの作成、保存、インポートのタスクを提供します.
    つまり、CRUDを使用するには、NSManagedObjectContextにファイルをインポートする必要があります.
    だから持ってきました.
    func saveFeed() {
            // hasChanges : 해당 Context가 바뀌었는지 체크
            if feedContext.hasChanges {
                // perform : ContextQueue에서 지정된 블록을 비동기적으로 수행한다.
                feedContext.perform {
                    do {
                        // save : 저장되지 않은 변경 사항을 등록된 개체에 대해 Context의 저장소에 저장한다.
                        try self.feedContext.save()
                    } catch {
                        fatalError(error.localizedDescription)
                    }
                }
            }
        }
    上記のコードは、コードの重複を防止するために、格納されたコードを別の方法でマイニングします.
    コードを簡単に見て、データがhasChangesに変更されたかどうかを確認します.performで非同期実行を行います.
    保存されていない情報であれば、save()として保存されたメソッドが呼び出されます.
    CRUD定義コードです.

    insert

    func insert(userImage: Data, userName: String, text: String, like: Int, uploadImage: Data, time: Date, completion: ((_ error: NSError?) -> Void)? = nil) {
            let feedArray = FeedArray(context: feedContext)
            feedArray.userImage = userImage
            feedArray.userName = userName
            feedArray.text = text
            feedArray.like = Int16(like)
            feedArray.uploadImage = uploadImage
            feedArray.time = time
            
            do {
                // validateForInsert : managed object를 현재 상태로 append할 수 있는지 여부를 결정한다.
                try feedArray.validateForInsert()
            // 에러 발생시
            } catch let error as NSError {
                // rollback : 모든 항목을 제거하고 모든 append 및 delete를 취소하고 업데이트 된 오브젝트 또한 마지막으로 올려진 값으로 복원한다.
                feedArray.managedObjectContext?.rollback()
                completion?(error)
                return
            }
            // 그게 아니면 저장하는 방법을 택한다.
            saveFeed()
            completion?(nil)
        }
    これは固定的な方法ではないと思います.
    しかし,コアデータ自体はデータベースではないため,実現方法は多様であると考えられる.
    そこで筆者はこう表現した.

    read

    func read() -> [FeedArray] {
            // NSFetchRequest : persistent store 에서 데이터를 검색하는 데 사용되는 검색 기준에 대한 정의가 담겨있는 클래스이다.
            // fetchRequest : 비동기적으로 실행되는 기본적인 가져오기 요청이다.
            let readRequest: NSFetchRequest<FeedArray> = FeedArray.fetchRequest()
            
            var feedList = [FeedArray]()
            
            // Sorting Function
            // NSSortDescriptor : 모든 오브젝트에 공통으로 적용되는 컬렉션을 적용하는 방법에 대한 클래스.
            // 특히 Sorting 과 관련된 기능들이 정의 되어있다.
            let sort = NSSortDescriptor(key: #keyPath(FeedArray.time), ascending: false)
            readRequest.sortDescriptors = [sort]
            // 블록 안의 작업이 Context에 대한 올바른 대기열에서 실행되는지 확인한다.
            feedContext.performAndWait {
                do {
                    // fetch : 위에서 정렬된 Entity를 기준으로 지정된 항목의 배열을 반환한다.
                    feedList = try feedContext.fetch(readRequest)
                } catch {
                    fatalError(error.localizedDescription)
                }
            }
            return feedList
        }
    readは、NSFetchRequestによって非同期にデータを取得する方法を用いる.
    また,時間順ソートはNSSortDescriptorを用いて行った.

    update

    func update(_ feedArray: FeedArray, userImage: Data, userName: String, text: String, like: Int, uploadImage: Data, time: Date, completion: (() -> Void)? = nil) {
            
            feedArray.userImage = userImage
            feedArray.userName = userName
            feedArray.text = text
            feedArray.like = Int16(like)
            feedArray.uploadImage = uploadImage
            feedArray.time = time
            
            saveFeed()
            completion?()
        }
    他のコードに比べてupdateは比較的簡単です.
    変更後の情報を再保存するだけなので、コードは簡単です.

    delete

    func delete(_ feedArray: FeedArray) {
            // delete : 변경사항을 저장할 때 영구 저장소에서 제거해야 하는 오브젝트를 지정한다.
            feedContext.delete(feedArray)
            saveFeed()
        }
    delete部分はcoreDataが提供するdeleteで、その配列を削除すればよい.
    そのままCoreDataを使用しました.
    理論は難しいが、実際には想像以上に使いやすい.