2017-01-07 3 views
3

私は3×iPhone 5の、私はiPhone 5のすべてのデバイスに上記のエラーを取得してい5S、6、6S、および7EXC_BAD_ACCESSコード= EXC_ARM_DA_ALIGN

で自分のコードをテストしてみました。ここで何が起こっているのかは分かりませんが、おそらく5ビットデバイスが32ビットデバイスであるということが手掛かりになるかもしれません。

私は設定変数は、単純な構造体であるのViewControllerクラスから

func startRecording() { 
    disableControls() 

    CoreDataStack.shared.performForegroundTask { (context) in 
      let sessionInfo = SessionInfo(context: context) 
      sessionInfo.startTime = Date().timeIntervalSince1970 
      sessionInfo.userId = self.config.userId 
      sessionInfo.devicePosition = self.config.devicePosition.rawValue 
      sessionInfo.deviceType = self.config.deviceType.rawValue 
      sessionInfo.deviceNumber = self.config.deviceNumber 
      sessionInfo.deviceSide = self.config.deviceSide.rawValue 

      do { 
        try context.obtainPermanentIDs(for: [sessionInfo]) 
      } catch { 
        print("Error obtaining permanent ID for session info record") 
        return 
      } 

      CoreDataStack.shared.saveViewContextAndWait() 

      DispatchQueue.main.async { 
        guard sessionInfo.objectID.isTemporaryID == false else { 
          print("ObjectID is temporary") 
          return 
        } 

        self.recording = true 
        self.statusLabel.text = "Recording..." 
        self.recordManager.start(sessionUID: sessionInfo.uid) 
      } 
    } 
} 

を次のメソッドを呼び出しています:

struct Configuration { 
    var userId: String = "Unknown" 
    var deviceType: DeviceType = .phone // enum: String 
    var deviceSide: DeviceSide = .notApplicable // enum: String 
    var deviceNumber: Int16 = 1 
    var devicePosition: DevicePosition = .waist // enum: String 
} 

CoreDataStackはここにある:

final class CoreDataStack { 
    static let shared = CoreDataStack() 
    private init() {} 

    var errorHandler: (Error) -> Void = { error in 
      log.error("\(error), \(error._userInfo)") 
    } 

    private struct constants { 
      static let persistentStoreName = "Model" 
    } 

    private lazy var persistentContainer: NSPersistentContainer = { 
      let container = NSPersistentContainer(name: constants.persistentStoreName) 
      container.loadPersistentStores(completionHandler: { [weak self] (storeDescription, error) in 
        if let error = error { 
          self?.errorHandler(error) 
        } 
      }) 
      return container 
    }() 

    lazy var viewContext: NSManagedObjectContext = { 
      self.persistentContainer.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump 
      self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true 
      try! self.persistentContainer.viewContext.setQueryGenerationFrom(.current) 
      return self.persistentContainer.viewContext 
    }() 

    private lazy var backgroundContext: NSManagedObjectContext = { 
      let context = self.persistentContainer.newBackgroundContext() 
      context.mergePolicy = NSMergePolicy.mergeByPropertyStoreTrump 
      return context 
    }() 

    func performForegroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) { 
      self.viewContext.performAndWait { 
        block(self.viewContext) 
      } 
    } 

    func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) { 
      backgroundContext.perform { 
        block(self.backgroundContext) 
      } 
    } 

    func saveBackgroundContext() { 
      viewContext.performAndWait { 
        do { 
          if self.viewContext.hasChanges { 
            try self.viewContext.save() 
          } 
        } catch { 
          self.errorHandler(error) 
        } 

        self.backgroundContext.perform { 
          do { 
            if self.backgroundContext.hasChanges { 
              try self.backgroundContext.save() 
              self.backgroundContext.refreshAllObjects() 
            } 
          } catch { 
            self.errorHandler(error) 
          } 
        } 
      } 
    } 

    func saveViewContext() { 
      viewContext.perform { 
        if self.viewContext.hasChanges { 
          do { 
            try self.viewContext.save() 
          } catch { 
            self.errorHandler(error) 
          } 
        } 
      } 
    } 

    func saveViewContextAndWait() { 
      viewContext.performAndWait { 
        if self.viewContext.hasChanges { 
          do { 
            try self.viewContext.save() 
          } catch { 
            self.errorHandler(error) 
          } 
        } 
      } 
    } 
} 

コードはstartRecordingメソッドの次の行に爆発しています:

try context.obtainPermanentIDs(for: [sessionInfo]) 

編集:

私だけCoreDataStackからなるストリップダウンテストアプリケーションと文字列型の一つの属性を持つ一方のエンティティでモデルを作成しました。私はまだ3倍のiPhone 5で同じエラーが発生しています。 5秒、6秒、6秒、7秒はすべて正常に動作します。

おそらくCoreDataStackに問題があるといえますか?

のGithubレポhere

+0

githubプロジェクトにCoreDataStack.swiftファイルがありません。ここからコピーすると「ログ」は利用できません。コメントを「ログアウト」して実行すると、iPhone 5を含むすべてのシミュレータで「成功」と表示されます。シミュレータまたは実際のデバイスでのみエラーが発生しますか? – oyalhi

+0

この問題の解決策または回避策を見つけましたか?私は多かれ少なかれ同じ問題を抱えており、それを理解することはできません。 –

答えて

0

私はあなたのコードで短い一見に基づいて推測のカップルを取るでしょう。

私の中の古い学校の開発者は、構成メンバーvar deviceNumber: Int16 = 1に引き付けられています。不正な位置合わせ設定または古いコンパイラは、次の項目の位置合わせが正しくない可能性があります。それを構造体の最後の項目にすることができます。

さらに目立つのは、sessionInfo.deviceNumber = self.config.deviceNumberという割り当てです。これは、問題の可能性がありますNSNumberにInt16を割り当てるように見えます。 (私はのSessionInfoが、全体的なコードとcontext引数を取り、その初期化子をもとにNSManagedObjectであると仮定しています。すべての数値のメンバーがNSNumbersある意味であろうと。)

私は

sessionInfo.deviceNumber = NSNumber(int:self.config.deviceNumber) 

にラインを変更してみてくださいコアデータへのiOS 10の追加にまだ精通していませんが、私がviewContextを読んでいるものからは読み取り専用です。しかし、このコードでは、viewContextを使って新しいオブジェクトを作成しています。デバッガでこの時点までXcodeコンソールに情報が表示されていますか?

+0

提案していただきありがとうございます。私はそれを試み、私が問題を解決するために考えることができるすべてを取り除いたが、何も働かなかった。私は問題を再現するために必要な最小限のコードで新しいプロジェクトを作成しました。 repoリンクの編集された質問を参照してください。あなたは一見を持つことができれば感謝します! – doovers

+0

両方の部分を試しましたか? NSNumberの部分はどうですか? (サンプルラインを含めるように私の答えを編集しました) –

+0

はいNSNumberも試しました。しかし、サンプルプロジェクトでは、すべての数値を削除し、エンティティには単一の文字列属性しか持たず、それはまだ起こっています。 – doovers

0

NSPersistentContainerは、コアデータスタックを使用するための設定が明確なセットアップです。あなたはそれを悪用しています。 viewContextは読み取り専用ですのでperformForegroundTasksaveViewContextおよびsaveViewContextAndWaitを削除してください。 viewContextのmergePolicyを変更しないでください。 performBackgroundTaskでは、同じメソッドシグネチャを持つNSPersistentContainerのperformBackgroundTaskを使用してください。 newBackgroundContextは使用しないでください。 NSPersistentContainerを使用している場合は、CoreDataStackは何もしないでください。

NSPersistentContainerとは異なるカスタムスタックが必要な場合は、NSPersistentContainerを使用しないでください。独自のスタックを作成してください。しかし、作成しようとしている設定に大きな問題があります。バックグラウンドコンテキストとviewContextの両方からの書き込みには、書き込みが同時に発生したときにメジャーの問題があります。 mergePolicyはそれを助けることができますが、あなたが保存したと思った情報が失われる可能性があります。 NSPersistentContainerが設定されているスタックを使用することを学ぶ方がはるかに優れています。

+0

提案をありがとう。あなたが言っているのは理にかなっていますが、私が明確にしていないことは、なぜnewBackgroundContextを使うことができないのかということです。私がやっているのは、共通のコンテキストで複数のオブジェクトを作成し、バッチで保存してI/Oを制限したいということです。その反対が示されていますか?また、適切なリソースがあれば、 'NSPersistentContainer'の適切な使用方法についても参考にしてください。 – doovers

+0

バッチで保存することをお勧めします。私は 'performBackgroundTask'を使ってそれを行うことを提案します。これは 'newBackgroundContext'よりも多くの利点があります。まず、コードが正しいスレッド上で実行されるようにします。次に、同時に2つの書き込みが発生しないようにします。第三に、これらの文脈は使い捨てであるという明確な期待をしています。あなたのブロックでそれらを使用してから、再度使用しないでください。私はそれが背景の文脈を抱いているより優れたシステムであることを発見しました。 –

+0

私はここで少し混乱しています。 'performBackgroundTask'への複数の呼び出しを使用してエンティティを作成すると、どのようにバッチで保存できますか? 1つのブロックにすべてのエンティティを作成することはできません。そのため、新しいエンティティごとに共通のコンテキストを作成するための 'newBackgroundContext'の使用について私が推論します。私はここで何が欠けていますか? – doovers

関連する問題