首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI/CoreData:同时访问0x7f92efc61cb8,但修改需要独占访问

SwiftUI/CoreData:同时访问0x7f92efc61cb8,但修改需要独占访问
EN

Stack Overflow用户
提问于 2020-11-30 20:48:36
回答 1查看 480关注 0票数 3

我正在使用SwiftUI和CoreData开发一个SwiftUI应用程序,遇到了一个我似乎搞不懂的问题。

为了提供一些我想要做的事情的信息:

我有两个CoreData实体,它们有一对多的关系:

  1. Tarantula -一只狼蛛可能多次蜕皮(对多只),当被删除时,所有的蜕皮也被移除(级联)
  2. molt -A蜕皮属于单一的tarantula (对一只),当被删除时,应该从Tarantula (无效)

中删除引用。

然后,我有一个观点,列出所有的蜕皮为一个给定的塔兰杜拉,允许添加和删除蜕皮。看起来是这样的:

代码语言:javascript
复制
struct MoltListView: View {
    private static let DATE_FORMATTER: DateFormatter = {
            let d = DateFormatter()
            d.dateFormat = "MMM d, y"
            return d
        }()
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @ObservedObject private var tarantula: Tarantula
    @FetchRequest private var molts: FetchedResults<Molt>
    @State private var userMessage: String = ""
    @State private var displayMessage: Bool = false
    
    init(tarantula: Tarantula) {
        self.tarantula = tarantula
        self._molts = FetchRequest(entity: Molt.entity(),
                                   sortDescriptors: [NSSortDescriptor(keyPath: \Molt.date, ascending: false)],
                                   predicate: NSPredicate(format: "tarantula = %@", tarantula))
    }
    
    var body: some View {
        List {
            Section(header: Text("Summary")) {
                Text("\(molts.count) Molt\(molts.count == 1 ? "" : "s")")
            }
            Section(header: Text("Molts")) {
                NavigationLink(destination: MoltView(tarantula: tarantula, molt: Molt.newModel())) {
                    Text("Add Molt").foregroundColor(.blue)
                }
                ForEach(molts, id: \.self) { molt in
                    NavigationLink(destination: MoltView(tarantula: tarantula, molt: molt)) {
                        Text(MoltListView.DATE_FORMATTER.string(from: molt.modelDate))
                    }
                }
                .onDelete(perform: deleteItems)
            }
        }.alert(isPresented: $displayMessage) {
            Alert(title: Text("Save Failure"), message: Text(userMessage), dismissButton: .default(Text("Ok")))
        }
    }
    
    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            offsets.map { molts[$0] }.forEach(viewContext.delete)

            do {
                try viewContext.save()
            } catch {
                viewContext.rollback()
                userMessage = "\(error): \(error.localizedDescription)"
                displayMessage.toggle()
            }
        }
    }
}

当我试图从列表视图中删除一个molt时,我正在经历的错误来自于。该应用程序立即崩溃,错误是:

代码语言:javascript
复制
Simultaneous accesses to 0x7ffb68d2c518, but modification requires exclusive access.
Previous access (a modification) started at SwiftUI`closure #2 in ListCoreCoordinator.tableView(_:commit:forRowAt:) + 53 (0x7fff56544a85).
Current access (a read) started at:
0    libswiftCore.dylib                 0x00007fff2f41fe90 swift_beginAccess + 568
1    SwiftUI                            0x00007fff56540670 ListCoreCoordinator.dataSource.getter + 50
2    SwiftUI                            0x00007fff56541140 ListCoreCoordinator.updateUITableView(_:to:transaction:) + 608
3    SwiftUI                            0x00007fff5653ff40 ListRepresentable.updateUIView(_:context:) + 892
4    SwiftUI                            0x00007fff569acc60 PlatformViewRepresentableAdaptor.updateViewProvider(_:context:) + 263
5    SwiftUI                            0x00007fff565e8ac0 closure #1 in closure #1 in closure #4 in closure #1 in PlatformViewChild.updateValue() + 229
6    SwiftUI                            0x00007fff565e89a0 closure #1 in closure #4 in closure #1 in PlatformViewChild.updateValue() + 195
7    SwiftUI                            0x00007fff56899b40 ViewRendererHost.performExternalUpdate(_:) + 186
8    SwiftUI                            0x00007fff565e8930 closure #4 in closure #1 in PlatformViewChild.updateValue() + 73
9    SwiftUI                            0x00007fff565e71e0 closure #1 in PlatformViewChild.updateValue() + 2363
10   SwiftUI                            0x00007fff565e6c40 PlatformViewChild.updateValue() + 650
11   SwiftUI                            0x00007fff562fa640 partial apply for implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 26
12   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
13   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
14   AttributeGraph                     0x00007fff4be91884 AG::Subgraph::update(unsigned int) + 781
15   SwiftUI                            0x00007fff5693a5f0 GraphHost.runTransaction() + 186
16   SwiftUI                            0x00007fff5693e110 GraphHost.runTransaction(_:) + 79
17   SwiftUI                            0x00007fff5693cba0 GraphHost.flushTransactions() + 211
18   SwiftUI                            0x00007fff5693bd40 specialized GraphHost.asyncTransaction<A>(_:mutation:style:) + 464
19   SwiftUI                            0x00007fff56509ac0 AttributeInvalidatingSubscriber.invalidateAttribute() + 236
20   SwiftUI                            0x00007fff56509a40 AttributeInvalidatingSubscriber.receive(_:) + 105
21   SwiftUI                            0x00007fff5650a0d0 protocol witness for Subscriber.receive(_:) in conformance AttributeInvalidatingSubscriber<A> + 16
22   SwiftUI                            0x00007fff5669a7e0 SubscriptionLifetime.Connection.receive(_:) + 89
23   Combine                            0x00007fff4ab32ec0 ObservableObjectPublisher.Inner.send() + 122
24   Combine                            0x00007fff4ab324b0 ObservableObjectPublisher.send() + 801
25   libswiftCoreData.dylib             0x00007fff53ebc900 @objc NSManagedObject._willChange_Swift_Trampoline() + 114
26   CoreData                           0x00007fff251b7e4f -[NSManagedObjectContext _postObjectsDidChangeNotificationWithUserInfo:] + 773
27   CoreData                           0x00007fff251c6b5b -[NSManagedObjectContext _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1825
28   CoreData                           0x00007fff251b8c0d -[NSManagedObjectContext _processRecentChanges:] + 1041
29   CoreData                           0x00007fff2511c241 -[NSManagedObjectContext save:] + 356
30   Tarantulas                         0x0000000101a14060 closure #1 in MoltListView.deleteItems(offsets:) + 1165
31   Tarantulas                         0x0000000101a07080 thunk for @callee_guaranteed () -> (@error @owned Error) + 15
32   Tarantulas                         0x0000000101a16b80 partial apply for thunk for @callee_guaranteed () -> (@error @owned Error) + 20
33   SwiftUI                            0x00007fff569b77e0 closure #1 in withTransaction<A>(_:_:) + 83
34   SwiftUI                            0x00007fff569b7860 partial apply for closure #1 in withTransaction<A>(_:_:) + 25
35   libswiftCore.dylib                 0x00007fff2f22b160 withExtendedLifetime<A, B>(_:_:) + 12
36   SwiftUI                            0x00007fff569b7690 withTransaction<A>(_:_:) + 66
37   SwiftUI                            0x00007fff569b7580 withAnimation<A>(_:_:) + 140
38   Tarantulas                         0x0000000101a13720 MoltListView.deleteItems(offsets:) + 375
39   Tarantulas                         0x0000000101a136e0 implicit closure #2 in implicit closure #1 in closure #2 in closure #1 in MoltListView.body.getter + 42
40   SwiftUI                            0x00007fff560c0700 partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed IndexSet) -> () + 17
41   SwiftUI                            0x00007fff56713c50 partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed IndexSet) -> (@out ()) + 17
42   SwiftUI                            0x00007fff560c0890 DeleteInteraction.delete() + 125
43   SwiftUI                            0x00007fff564a0090 SystemListDataSource.deleteCell(forRowAt:) + 64
44   SwiftUI                            0x00007fff56660d40 ShadowListDataSource.commitUpdates() + 963
45   SwiftUI                            0x00007fff56544a50 closure #2 in ListCoreCoordinator.tableView(_:commit:forRowAt:) + 76
46   SwiftUI                            0x00007fff56544730 ListCoreCoordinator.tableView(_:commit:forRowAt:) + 455
47   SwiftUI                            0x00007fff56544ab0 @objc ListCoreCoordinator.tableView(_:commit:forRowAt:) + 131
48   UIKitCore                          0x00007fff248ade86 -[UITableView _animateDeletionOfRowAtIndexPath:] + 188
49   UIKitCore                          0x00007fff248b68d7 __82-[UITableView _contextualActionForDeletingRowAtIndexPath:usingPresentationValues:]_block_invoke + 60
50   UIKitCore                          0x00007fff247fe817 -[UIContextualAction executeHandlerWithView:completionHandler:] + 148
51   UIKitCore                          0x00007fff2480c7b4 -[UISwipeOccurrence _executeLifecycleForPerformedAction:sourceView:completionHandler:] + 656
52   UIKitCore                          0x00007fff2480cf2d -[UISwipeOccurrence _performSwipeAction:inPullView:swipeInfo:] + 621
53   UIKitCore                          0x00007fff2480ec53 -[UISwipeOccurrence swipeActionPullView:tappedAction:] + 92
54   UIKitCore                          0x00007fff24816a96 -[UISwipeActionPullView _tappedButton:] + 148
55   UIKitCore                          0x00007fff2467b5db -[UIApplication sendAction:to:from:forEvent:] + 83
56   UIKitCore                          0x00007fff23fa488d -[UIControl sendAction:to:forEvent:] + 223
57   UIKitCore                          0x00007fff23fa4b43 -[UIControl _sendActionsForEvents:withEvent:] + 332
58   UIKitCore                          0x00007fff23fa3384 -[UIControl touchesEnded:withEvent:] + 500
59   UIKitCore                          0x00007fff241a546a _UIGestureEnvironmentUpdate + 8849
60   UIKitCore                          0x00007fff241a4c77 -[UIGestureEnvironment _updateForEvent:window:] + 887
61   UIKitCore                          0x00007fff246b893d -[UIWindow sendEvent:] + 4752
62   UIKitCore                          0x00007fff2469367d -[UIApplication sendEvent:] + 633
63   UIKitCore                          0x00007fff24720d55 __processEventQueue + 13895
64   UIKitCore                          0x00007fff2471aca7 __eventFetcherSourceCallback + 104
65   CoreFoundation                     0x00007fff2038c369 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
66   CoreFoundation                     0x00007fff2038c1be __CFRunLoopDoSource0 + 180
67   CoreFoundation                     0x00007fff2038b65c __CFRunLoopDoSources0 + 248
68   CoreFoundation                     0x00007fff20385bb1 __CFRunLoopRun + 878
69   CoreFoundation                     0x00007fff2038548f CFRunLoopRunSpecific + 567
70   GraphicsServices                   0x00007fff2b76ad28 GSEventRunModal + 139
71   UIKitCore                          0x00007fff24674df7 -[UIApplication _run] + 912
72   UIKitCore                          0x00007fff24679fd3 UIApplicationMain + 101
73   SwiftUI                            0x00007fff568cfc60 closure #1 in KitRendererCommon(_:) + 119
74   SwiftUI                            0x00007fff568cfbc0 runApp<A>(_:) + 143
75   SwiftUI                            0x00007fff56407980 static App.main() + 61
76   Tarantulas                         0x0000000101a17940 static TarantulasApp.$main() + 33
77   Tarantulas                         0x0000000101a17c20 main + 20
78   libdyld.dylib                      0x00007fff20256408 start + 1

我能够防止此错误的唯一方法是删除Molt->Tarantula关系中的删除规则,使其从无效变为不采取任何行动。然而,对我来说,这似乎更像是黑客,而不是修复。

我想知道是否有人曾经经历过这个问题,或者也许能够帮助我解决这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-02 23:41:25

此问题已被证实是由于系统错误造成的。

解决方法是在NSManagedObjectContext.perform中封装删除逻辑。例如:

代码语言:javascript
复制
private func deleteItems(offsets: IndexSet) {
    withAnimation {
        viewContext.perform { // HERE
            offsets.map { molts[$0] }.forEach(viewContext.delete)
            do {
                try viewContext.save()
            } catch {
                viewContext.rollback()
                userMessage = "\(error): \(error.localizedDescription)"
                displayMessage.toggle()
            }
        }
    }
}

作为参考,这里是苹果开发者论坛上与这个问题相关的帖子:https://developer.apple.com/forums/thread/668299

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65080970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档