【发布时间】:2016-09-25 10:25:11
【问题描述】:
抱歉,帖子太长了;但是,我想通过。
我有多个托管对象上下文 (moc) 和大量稳定且一致地运行的代码。除了当前的问题。奇怪的是 moc 的地址不是我创建的地址 - 一个不相关的 moc 正在崩溃,我什至无法访问。有时间请继续阅读。
简单地说,我创建了一个新的子 moc 并将其传递给新的视图控制器。用户设置一些值并保存它们。子 moc 被保存,然后是父级。但是,在编辑视图控制器中,如果用户选择显示 Google Place Picker,就像开始显示窗口一样,我会收到多线程错误。我在 iPhone 6 Plus 实际设备上收到此错误,但在 iPhone 6S 上没有。它没有任何问题。使用 6 Plus,总是在完全相同的地方崩溃。
我已启用com.apple.CoreData.ConcurrencyDebug 1
这是创建子视图进行编辑的主视图:
// =========================================================================
// 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)
}
}
这是声明属性的编辑视图控制器:
// =========================================================================
// EditEventTableViewController
class EditEventTableViewController: UITableViewController {
// =========================================================================
// MARK: - Google Place properties
private var context: NSManagedObjectContext!
private var placePicker: GMSPlacePicker!
}
这是我调用显示地图功能的地方:
// =========================================================================
// 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 beta (8T29o)、Swift 2.3,但在 Xcode 7.3.1 上看到了相同的行为。
非常感谢任何指针。
中断时的堆栈如下所示。它不显示违规发生在哪一行。如果是这样,那么追踪错误会容易得多。
EDIT 1 - 保存功能
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)
}
}
}
【问题讨论】:
标签: swift multithreading core-data google-places-api