2016-09-25 14 views
0

申し訳ありませんが、長い投稿;しかし、私は通っていたかった。無関係な管理オブジェクトコンテキストを使用したGoogleプレイスピッカーのCoreDataスレッドの問題

Iが複数の管理オブジェクトコンテキスト(MOC)と一貫して安定して作業かなりのコードを有しています。現在の問題を除いて。奇妙なことは、モックのアドレスは、私が作成したもののどれでもないことです。無関係のモックは、私がアクセスしていないということでクラッシュしています。時間があればお読みください。

非常に単純に、私クレートに新しい子MOCを入れて、新しいビューコントローラにそれを渡します。ユーザーがいくつかの値を設定して保存します。子モックが保存され、親が保存されます。ただし、編集ビューコントローラでは、ユーザーがGoogle Place Pickerを表示するように選択した場合、ウィンドウの表示を開始すると同時にマルチスレッドエラーが発生します。 iPhone 6 Plusでは実際のデバイスでこのエラーが発生しますが、iPhone 6Sでは発生しません。それはまったく問題なく動作します。 6 Plusでは常に同じ場所でクラッシュします。

// ========================================================================= 
// EditEventTableViewController 
class EditEventTableViewController: UITableViewController { 
    // ========================================================================= 
    // MARK: - Google Place properties 
    private var context: NSManagedObjectContext! 
    private var placePicker: GMSPlacePicker! 
} 

// ========================================================================= 
// EventsTableViewController 
class EventsTableViewController: UITableViewController { 
    // ========================================================================= 
    // MARK: - Target Action Methods 
    @IBAction func didTapNewEvent(sender: UIBarButtonItem) { 
     guard let vc = storyboard?.instantiateViewControllerWithIdentifier(EditEventTableViewController.identifier) as? EditEventTableViewController else { DLog("ERROR creating EditEventTableViewController"); return } 

     // create a child context 
     let eventContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) 
     eventContext.parentContext = context 
     eventContext.name = "child_of_mainContext_for_Event" 
     let event = NSEntityDescription.insertNewObjectForEntityForName(Event.entityName, inManagedObjectContext: eventContext) 
     vc.segueObject = event 
     vc.context = eventContext 
     vc.shouldDismiss = true 
     vc.delegate = self 
     let nc = UINavigationController(rootViewController: vc) 
     presentViewController(nc, animated: true, completion: nil) 
    } 
} 

これは、プロパティが宣言されている編集ビューコントローラである:私はこれは編集のために子ビューを作成し、メインwiewあるcom.apple.CoreData.ConcurrencyDebug 1

を有効にしている

ここで私はショーマップ機能と呼んでいます:

// ========================================================================= 
// MARK: - UITableViewDelegate 
extension EditEventTableViewController { 
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
     if indexPath == Cell.Location.indexPath { 
      didTapSelectFromMap() 
     } 
    } 
} 

これは、コードはまったく同じスポットたびにクラッシュし、私も(私は実際にだったが、彼らが問題を解決しなかった削除)ここで任意のコンテキストにアクセスしていない午前、Googleの場所ピッカーです:

// ========================================================================= 
// MARK: - Google Places 
extension EditEventTableViewController { 
    func didTapSelectFromMap() { 
     guard let event = selectedObject as? Event else { DLog("ERROR object is not Event"); return } 
     guard let location = locationManager.location else { 
      DLog("Cannot get location, will try again") 
      locationManager.startUpdatingLocation() 
      return 
     } 

     DLog("current location: \(location)") 

     // create viewport around where the user is 
     let center = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude) 
     let northEast = CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001) 
     let southWest = CLLocationCoordinate2DMake(center.latitude - 0.001, center.longitude - 0.001) 
     let viewport = GMSCoordinateBounds(coordinate: northEast, coordinate: southWest) 
     let config = GMSPlacePickerConfig(viewport: viewport) 

     placePicker = GMSPlacePicker(config: config) 

     placePicker.pickPlaceWithCallback {  // the code crashes here! But I have no idea where the violation occurs. 
      (place, error) in 

     } 
    } 
} 

私はすべてをログに書き、ログから関連する情報を以下に示します。ご覧のように、私は4つのコンテキストを作成しますが、アドレスは表示されますが、私が作成していないMOCにはエラーがあります。それは、GooglePlacePickerがそれ自身のmocを使用していて、何とか私のものと混合しているかもしれません:)???

[00059]:CDStack.swift     :parentContext................. :12:41:18 CREATED <NSManagedObjectContext: 0x1741dbe40>: parent 
[00068]:CDStack.swift     :context....................... :12:41:18 CREATED <NSManagedObjectContext: 0x1741dbd50>: main 
[00077]:CDStack.swift     :importContext................. :12:41:18 CREATED <NSManagedObjectContext: 0x1701dd3d0>: import 
[00095]:CDStack.swift     :firebaseContext............... :12:41:21 CREATED <NSManagedObjectContext: 0x1741dc020>: firebase 
[00127]:EditEventTableViewController.s :viewDidLoad()................. :12:43:48 Context: <NSManagedObjectContext: 0x1741de3c0>: child_of_mainContext_for_Event 
[00375]:EditEventTableViewController.s :didTapSelectFromMap()......... :12:43:54 current location: <+78.675603,-93.352320> +/- 1414.00m (speed -1.00 mps/course -1.00) @ 25/09/2016, 12:43:54 Southern European Spring Time 
2016-09-25 12:43:54.630499 App[1504:413029] [error] error: The current thread is not the recognized owner of this NSManagedObjectContext(0x1703c3de0). Illegal access during objectRegisteredForID: 

私は、Xcodeのバージョン8.1ベータ(8T29o)を使用して、スウィフト2.3が、Xcodeのバージョン7.3.1と同じ動作を見ています。

どのポインタも大変ありがとうございます。

ブレーク時のスタックを以下に示します。違反が発生した行は表示されません。もしそうならば、バグを追跡するほうがはるかに簡単でした。

CorData Multithread Violation

EDIT 1 - 保存機能あなたは-[GMSTileDataCache storeCacheableTileDatas:completionHandler:]完了ブロックで-[NSManagedObjectContext save:]を呼び出している

class func save(moc:NSManagedObjectContext) { 
    moc.performBlockAndWait { 
     if moc.hasChanges { 
      do { 
       try moc.save() 
      } catch { 
       DLog("ERROR saving context '\(moc)' - \(error)") 
      } 
     } else { 
      // there are no changes 
     } 
     if let parentContext = moc.parentContext { 
      save(parentContext) 
     } 
    } 
} 

答えて

0

。それはバックグラウンドスレッドで実行されていると私はあなたがバックグラウンドスレッドに関連付けられていないコンテキストで保存を呼び出すと思われる。

すぐに回答を保存するには、-performBlockAndWait:に保存してください。

+0

私はこれらの機能を呼び出すことはありません。これらはGoogle Place Pickerライブラリの中にあります。私は '-performBlockAndWait'を使ってマネージドオブジェクトコンテキストを保存するための' CDStack'という名前のシングルトンを持っています。私はそこにブレークポイントを置くと決して呼び出されません。私は違反がGoogle図書館の内部にあると考え始めており、文脈はそこに属しています。これも可能ですか?私はコードを編集して保存機能を表示しました。私は決して**他のどこにも救いません。上記の 'didTapSelectFromMap()'はその時点で実行されている唯一のコードです。 – oyalhi

+1

Googleコードにスレッドエラーが発生している可能性があります。私はその方法のソースを見て、可能であればそれを変更して問題を修正することを提案することをお勧めします。 –

+0

私はGoogleがこれらの機能を公開するとは思わない。私が考えることができる最良の方法は、Google Place Pickerで非常に簡単なCore Dataプロジェクトを作成し、スレッドに違反すると思われる 'pickPlaceWithCallback'を呼び出すことです。あなたのご意見ありがとうございます、私はそれを感謝します。 – oyalhi

関連する問題