在模式视图中编辑TextView时如何处理(或避免)“无法更改NSManagedObjectContext的保留策略...”

我正在构建的iOS应用会遍历Core Data中定义的PhraseGroup对象的列表,并显示与每个extraText关联的PhraseGroup内容。这显示了PhraseGroup的定义方式:

extension PhraseGroup {

@nonobjc public class func fetchRequest() -> NSFetchRequest<PhraseGroup> {
    return NSFetchRequest<PhraseGroup>(entityName: "PhraseGroup")
}

@NSManaged public var extraText: String
@NSManaged public var phraseGroupID: UUID
@NSManaged public var text: String
@NSManaged public var phrase: NSSet?
@NSManaged public var piece: Piece

我希望用户能够长按列表中的任何extraText条目,然后在模式表中编辑此字段。我不想为此使用NavigationLink,因为我想将此类链接用于其他功能。

下面显示了我如何列出短语组以及如何显示模式表:

import SwiftUI
import CoreData

struct PhraseGroupView: View {

@Environment(\.managedobjectcontext) var moc
@Binding var phraseGroupViewAlertItem: AlertItem?
@State private var isEditMode: EditMode = .inactive
@State private var phraseGroupObjectID: nsmanagedobjectid? = nil

private var fetchRequest: FetchRequest<PhraseGroup>
private var phraseGroups: FetchedResults<PhraseGroup> { fetchRequest.wrappedValue }

var body: some View {
NavigationView {
    VStack(spacing: 20){
        Section {
            List {
                ForEach (phraseGroups,id: (\PhraseGroup.phraseGroupID)) { phraseGroup in
                    HStack {
                        Text("\(phraseGroup.wrappedExtraText)")
                    }
                    .onLongPressGesture {
                        phraseGroupObjectID = phraseGroup.objectID
                    }
                }
                .onDelete(perform: delete)
            }
            .sheet(item: self.$phraseGroupObjectID) { objID in
                TestPhraseGroupEditView(phraseGroupObjectID: objID).environment(\.managedobjectcontext,self.moc)
            }
        }
    }
    .navigationBarTitle("This is phraseGroup navBarTitle",displayMode: .inline)
    .navigationBarItems(leading:
                            HStack {
                                Button(action: {
                                    // yet to come
                                }) {
                                    Image(systemName: "plus").resizable()
                                        .frame(width: 16,height: 16)
                                        .aspectRatio(contentMode: .fit)
                                        .foregroundColor(.myKeyColor)
                                }
                            },trailing:
                                HStack {
                                    EditButton()
                                        .frame(width: 60,height: 20)
                                        .aspectRatio(contentMode: .fit)
                                        .foregroundColor(.myKeyColor)
                                })
    .environment(\.editMode,self.$isEditMode)
  }
}

init (phraseGroupViewAlertItem: Binding<AlertItem?>,piece: Piece) {
    self._phraseGroupViewAlertItem = phraseGroupViewAlertItem
    fetchRequest = FetchRequest<PhraseGroup>(
        entity: PhraseGroup.entity(),sortDescriptors: [
            NSSortDescriptor(key: "extraText",ascending: true)
        ],predicate: NSPredicate(format: "piece == %@",piece)
        // 'piece' in the predicate above is the name of a Piece <- PhraseGroup relationship defined in Core Data
    )
}

这是我的模态表(目前有很多裸露的骨头,尚未尝试包括保存功能):

import SwiftUI
import CoreData

  struct TestPhraseGroupEditView: View {

@Environment(\.managedobjectcontext) var moc
@State private var extraTextForEditing = ""
var phraseGroupObjectID: nsmanagedobjectid!

var phraseGroup: PhraseGroup {
        moc.object(with: phraseGroupObjectID) as! PhraseGroup
    }

var body: some View {
    NavigationView {
        Form {
            Section {
                TextField("Extra Text",text: $extraTextForEditing)
            }
        }
    }
    .onAppear {
        phraseGroup.managedobjectcontext!.performAndWait {
            extraTextForEditing = phraseGroup.extraText
        }
    }
  }
}

长按上一个列表后,此表显示良好。但是,当我打开TextField进行输入时,应用程序会以NSInternalInconsistencyException

的原因抛出An NSmanagedobjectcontext's retain policy cannot be changed while it has registered objects. Trying using reset() first.

我认为,我的容器和托管对象上下文的设置非常传统。唯一有点不寻常的功能是,我在将托管对象上下文添加到环境的同时,添加了Singleton PiecePlayer(应用程序的音频管理类)作为环境对象。

这是AppDelegate.swift的容器部分:

lazy var persistentContainer: NSPersistentContainer = {

    let container = NSPersistentContainer(name: "AK6")
    container.loadPersistentStores(completionHandler: { (storeDescription,error) in
        if let error = error as NSError? {

            fatalError("Unresolved error \(error),\(error.userInfo)")
        }
    })
    return container
}()

这是SceneDelegate.swift中上下文的设置:

class SceneDelegate: UIResponder,UIWindowSceneDelegate {

var window: UIWindow?
var pp = PiecePlayer()
@Environment(\.managedobjectcontext) var moc

func scene(_ scene: UIScene,willConnectTo session: UIScenesession,options connectionOptions: UIScene.ConnectionOptions) {

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
    let contentView = ContentView().environment(\.managedobjectcontext,context).environmentObject(pp)

关于它的价值,我尝试在SceneDelegate.swift中显式设置context.retainsRegisteredObjects = false,但这对抑制此错误没有影响。我相信无论如何这都是默认设置。

https://davedelong.com/blog/2018/05/09/the-laws-of-core-data/的警告提示了我在onAppear()中对performAndWait的使用,该警告涉及从不同的受管对象上下文更改“相同”对象的危险,但即使在阅读了有关不继承{{1 }},因为它们已从应用程序的视图层次结构中分离出来,所以我不认为这是这里发生的事情。为了更加安全,我在调用托管对象上下文时将其传递给模态视图,并在调试器中检查模态视图的托管对象上下文显示它不是nil,并且它没有父对象-两者这向我暗示我正在处理“正确的”托管对象上下文。

如果我只能正式地捕获它,是否有可能该异常实际上是良性的?如果是这样,我如何以及在哪里可以捕获到异常?另一种方法(大概是最好的方法)是,有没有一种方法可以避免我首先触发此异常?

guozili1983 回答:在模式视图中编辑TextView时如何处理(或避免)“无法更改NSManagedObjectContext的保留策略...”

新手错误。发生错误后,无法检查Xcode中的原始异常回溯。完成后,我发现我将在应用程序的初始窗口中设置moc.retainsRegisteredObjects = true(在我的帖子中未显示)。消除它可以解决问题。

本文链接:https://www.f2er.com/1499900.html

大家都在问