web-dev-qa-db-ja.com

既存のXcode 9にコアデータを追加する方法Swift 4 iOS 11プロジェクト?

この質問はもちろん以前のバージョンで回答されているため、更新が必要です。12/ 16日付の最新の検索結果は、以前のiOS 9および10プロジェクトとは無関係な互換性を生成します。

もちろん、ドキュメントでは、新しいプロジェクトを開始するときに[コアデータを使用する]チェックボックスを選択しますが、選択しませんでしたが、iCloud + Core Dataを追加してアプリを次のフェーズに進める必要があると考えています-> NSFileCoordinatorなどNSFilePresenterが必要なのは、私のアプリのUIユーザーには多くのトピックが表示され、各トピックには3つのオプションがあり、どのユーザーが1つのオプションを選択するかについてです。各トピックについて、UIは各オプションを選択したユーザーの総数と各オプションの合計の割合を表示します。

現在、各オプションの選択肢の数と合計の割合は、もちろん私のネイティブアプリで計算されています->しかし、実際にはクラウドのような中央の場所で、またはおそらくウェブサイトで計算する必要があります。 NSFileCoordinatorとNSFilePresenterがすでに解決した同時読み取り/書き込みの問題を発生させます。

そのため、iCloud + Core Dataシステムが既存のユビキタスコンテナーの数値合計に基本的な算術計算を挿入できる場合-クラウド内で個々のユーザーから数値書き込みコマンドを受信すると-新しいユビキタスコンテナーの合計数値とパーセント値を送信する前に-そしてコアデータスタックの作成と初期化を試みる際に、以下で生成されるエラーをどのように修正するかについてアドバイスをいただければ幸いです。そうでなければ、仕事に最適な場合はXcodeをスクレイプしてPhoneGapなどのハイブリッドアプリに移動する必要があると思います。

したがって、コアデータプログラミングガイドを参照してください。

https://developer.Apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html#//Apple_ref/doc/uid/TP40001075-CH4-SW1

既存のプロジェクトの最初に次のコードを貼り付けて、生成します

未解決の識別子「persistentContainer」の使用…「managedObjectContext」

...エラー。そしてライン

init(completionClosure: @escaping () -> ()) { 

...生成

初期化子は型内でのみ宣言できます

import UIKit

import CoreData
class DataController: NSObject {
  var managedObjectContext: NSManagedObjectContext
  init(completionClosure: @escaping () -> ()) {
    persistentContainer = NSPersistentContainer(name: "DataModel")
    persistentContainer.loadPersistentStores() { (description, error) in
      if let error = error {
        fatalError("Failed to load Core Data stack: \(error)")
      }
      completionClosure()
    }
  }
}

init(completionClosure: @escaping () -> ()) {
  //This resource is the same name as your xcdatamodeld contained in your project
  guard let modelURL = Bundle.main.url(forResource: "DataModel", withExtension:"momd") else {
    fatalError("Error loading model from bundle")
  }
  // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
  guard let mom = NSManagedObjectModel(contentsOf: modelURL) else {
    fatalError("Error initializing mom from: \(modelURL)")
  }

  let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)

  managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
  managedObjectContext.persistentStoreCoordinator = psc

  let queue = DispatchQueue.global(qos: DispatchQoS.QoSClass.background)
  queue.async {
    guard let docURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last else {
      fatalError("Unable to resolve document directory")
    }
    let storeURL = docURL.appendingPathComponent("DataModel.sqlite")
    do {
      try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
      //The callback block is expected to complete the User Interface and therefore should be presented back on the main queue so that the user interface does not need to be concerned with which queue this call is coming from.
      DispatchQueue.main.sync(execute: completionClosure)
    } catch {
      fatalError("Error migrating store: \(error)")
    }
  }
}

// followed by my existing working code:

class ViewController: UIViewController {
13
ehounder

File> new file ... select core Data under iOSを選択し、Data Modelを選択しますプロジェクトの作成中にコアデータを選択するたびにxcodeが自動生成するコードが必要です。取得するには、コアデータオプションcheckedで新しいプロジェクトを作成し、** // Mark:AppDelegate.Swiftで記述されたすべてのコードをコピーします。 =および追加

import CoreData

[〜#〜] optional [〜#〜]

lazy var persistentContainerの完了ブロックをコピーした後、アプリの名前を変更することを忘れないでください。この部分でアプリの名前を変更する* NSPersistentContainer(name: "SHOULD-BE-THE-NAME-OF-YOUR-APP")そして、コピーしたコードのmanagedObjectModel関数**

35
Jay N.

あなたが私のような怠け者の場合、新しいCore Dataプロジェクトからコピーする必要があるすべてのコードを以下に示します...(なぜ誰もが新しいプロジェクトを作成するのですか?) YOUR_APP_NAME_HEREを変更

import CoreData


// MARK: - Core Data stack

func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        // Saves changes in the application's managed object context before the application terminates.
        self.saveContext()
    }

lazy var persistentContainer: NSPersistentContainer = {
    /*
     The persistent container for the application. This implementation
     creates and returns a container, having loaded the store for the
     application to it. This property is optional since there are legitimate
     error conditions that could cause the creation of the store to fail.
    */
    let container = NSPersistentContainer(name: "YOUR_APP_NAME_HERE")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            /*
             Typical reasons for an error here include:
             * The parent directory does not exist, cannot be created, or disallows writing.
             * The persistent store is not accessible, due to permissions or data protection when the device is locked.
             * The device is out of space.
             * The store could not be migrated to the current model version.
             Check the error message to determine what the actual problem was.
             */
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

// MARK: - Core Data Saving support

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}
11
iOSDevSF

私はこれが答えられていることを知っていますが、実際の問題はAppleのドキュメントにあると思います。 Objective-CコードをSwiftコードと比較すると、var managedObjectContext: NSManagedObjectContextが実際に定義されていないことがわかります。この行をvar persistentContainer: NSPersistentContainerで置き換える必要があります。 Objective-cインターフェース

@interface MyDataController : NSObject
@property (strong, nonatomic, readonly) NSPersistentContainer *persistentContainer; 
- (id)initWithCompletionBlock:(CallbackBlock)callback;
@end

したがって、DataController.Swiftは次のようになります。

class DataController: NSObject {
 // Delete this line   var managedObjectContext: NSManagedObjectContext
    var persistentContainer: NSPersistentContainer
    init(completionClosure: @escaping () -> ()) {
        persistentContainer = NSPersistentContainer(name: "DataModel")
        persistentContainer.loadPersistentStores() { (description, error) in
          if let error = error {
              fatalError("Failed to load Core Data stack: \(error)")
          }
          completionClosure()
       }
    }
}

コードの残りの部分については、 Apple Docs は必要ありません。

IOS 10およびmacOS 10.12より前では、Core Dataスタックの作成がより複雑でした。

コードのそのセクションは、古い方法を示しています。

3
hidden-username