- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 CDPassingQ 有一个最小的示例项目
我的主要(ContentView)看起来像:
import SwiftUI
import CoreData
struct ContentView: View {
@Environment( \.managedObjectContext ) private var viewContext
@FetchRequest( sortDescriptors: [ NSSortDescriptor( keyPath: \Item.name, ascending: true ) ],
animation: .default )
private var items: FetchedResults<Item>
var body: some View {
NavigationView {
List {
ForEach( items ) { item in
NavigationLink {
NameViewer( itemID: item.objectID )
} label: {
Text( item.name! )
}
}
.onDelete( perform: deleteItems )
}
.toolbar {
ToolbarItem( placement: .navigationBarTrailing ) {
EditButton()
}
ToolbarItem {
Button() {
print( "Add Item" )
} label: {
NavigationLink {
NameViewer();
} label: {
Label( "Add Item", systemImage: "plus" )
}
}
}
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
和NameViewer看起来像:
import SwiftUI
import CoreData
enum TrustReason: String, Identifiable, CaseIterable
{
var id: UUID
{
return UUID();
}
case unknown = "Unknown";
case legalOnly = "Legal Only";
case goodLabeling = "Good Labeling";
case facilityClean = "Facility Clean";
case detailedAnswers = "Detailed Answers";
case unresponsive = "Unresponsive";
}
extension TrustReason
{
var title: String
{
switch self
{
case .unknown:
return "Unknown";
case .legalOnly:
return "Legal Only";
case .goodLabeling:
return "Good Labeling";
case .facilityClean:
return "Facility Clean";
case .detailedAnswers:
return "Detailed Answers";
case .unresponsive:
return "Unresponsive";
}
}
}
struct NameViewer: View {
@Environment( \.presentationMode ) var presentationMode
@Environment( \.managedObjectContext ) private var moc
@State private var name: String = ""
@State private var reason: TrustReason = .unknown
var itemID: NSManagedObjectID?
var body: some View {
Form {
Section( header: Text( "Information" ) ) {
TextField( "Name", text: $name )
}
Section( header: Text( "Trust" ) ) {
Picker( "Reason", selection: $reason ) {
ForEach( TrustReason.allCases ) { trustReason in
Text( trustReason.title ).tag( trustReason )
}
}
}
}
.toolbar {
Button() {
if ( saveName() ) {
self.presentationMode.wrappedValue.dismiss()
}
} label: {
Text( "Save" )
}
}
.onAppear {
print( "on appear" )
guard let theID = itemID,
let item = moc.object( with: theID ) as? Item else {
return
}
print( "passed guard" )
if let itemName = item.name {
name = itemName
}
print( name )
}
}
private func saveName() -> Bool {
let item = Item( context: moc )
do {
print( self.name )
item.name = self.name
try moc.save()
return true
} catch {
print( error )
print( error.localizedDescription )
}
self.moc.rollback();
return false
}
}
struct NameViewer_Previews: PreviewProvider {
static var previews: some View {
NameViewer()
}
}
我可以创建新项目以显示在 ContentView 的列表中。
然后,当我在列表中选择一个项目时,我将该项目传递给 NameViewer。我可以确认我在 .onAppear 代码中成功找到了正确的对象。
但是,有两个问题:
如果我在列表中选择一个项目,除非我先点击文本字段,否则项目名称不会出现在名称文本字段中。'
使用 .onAppear 似乎不是放置该代码的正确位置。原因是 Picker 将另一个 View 插入堆栈,一旦项目被选中,.onAppear 再次运行并且我丢失了对名称字段的更改名称。
如何更改代码以解决这些问题?
最佳答案
为了实现所需的功能,我会在 UI 和核心数据方面更改您的架构。
在用户界面方面,最好使用导航链接来显示静态数据详细 View ,并使用模式来执行数据操作,例如创建和编辑对象。因此,有一个 View 显示对象详细信息(例如 NameViewer
),另一个 View 用于编辑对象(例如 NameEditor
)。此外,将 NSManagedObject
子类的属性直接绑定(bind)到 SwiftUI 控件。不要创建额外的 @State
属性,然后复制值。您正在引入一个共享状态,这是 SwiftUI 旨在消除的东西。
在核心数据方面,为了执行创建和更新操作,您需要使用子上下文。每当您创建或更新对象时,都会显示一个注入(inject)了子上下文的模态编辑器 View 。这样,如果我们对我们的更改不满意,我们可以简单地忽略该模式,并且更改会被神奇地丢弃,而无需调用 rollback()
,因为该子上下文已随 View 一起销毁。由于您现在正在使用子上下文,因此不要忘记将主视图上下文也保存在某个地方,例如当用户导航出您的应用时。
所以为了在代码中实现它,我们需要一些结构来存储我们新创建的对象以及它们的子上下文:
struct CreateOperation<Object: NSManagedObject>: Identifiable {
let id = UUID()
let childContext: NSManagedObjectContext
let childObject: Object
init(with parentContext: NSManagedObjectContext) {
let childContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
childContext.parent = parentContext
let childObject = Object(context: childContext)
self.childContext = childContext
self.childObject = childObject
}
}
struct UpdateOperation<Object: NSManagedObject>: Identifiable {
let id = UUID()
let childContext: NSManagedObjectContext
let childObject: Object
init?(
withExistingObject object: Object,
in parentContext: NSManagedObjectContext
) {
let childContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
childContext.parent = parentContext
guard let childObject = try? childContext.existingObject(with: object.objectID) as? Object else { return nil }
self.childContext = childContext
self.childObject = childObject
}
}
UI代码如下:
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.name, ascending: true)], animation: .default
) private var items: FetchedResults<Item>
@State private var itemCreateOperation: CreateOperation<Item>?
var body: some View {
NavigationView {
List {
ForEach(items) { item in
NavigationLink {
NameViewer(item: item)
} label: {
Text(item.name ?? "")
}
}
}
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
EditButton()
Button(action: {
itemCreateOperation = CreateOperation(with: viewContext)
}) {
Label("Add Item", systemImage: "plus")
}
}
}
.sheet(item: $itemCreateOperation) { createOperation in
NavigationView {
NameEditor(item: createOperation.childObject)
.navigationTitle("New Item")
}
.environment(\.managedObjectContext, createOperation.childContext)
}
}
}
}
struct NameViewer: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var itemUpdateOperation: UpdateOperation<Item>?
@ObservedObject var item: Item
var body: some View {
Form {
Section {
Text(item.name ?? "")
}
}
.navigationTitle("Item")
.toolbar {
Button("Update") {
itemUpdateOperation = UpdateOperation(withExistingObject: item, in: viewContext)
}
}
.sheet(item: $itemUpdateOperation) { updateOperation in
NavigationView {
NameEditor(item: updateOperation.childObject)
.navigationTitle("Update Item")
}
.environment(\.managedObjectContext, updateOperation.childContext)
}
}
}
struct NameEditor: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.managedObjectContext) private var childContext
@ObservedObject var item: Item
var body: some View {
Form {
Section(header: Text("Information")) {
if let name = Binding($item.name) {
TextField("Name", text: name)
}
}
}
.toolbar {
Button() {
try? childContext.save()
dismiss()
} label: {
Text("Save")
}
}
}
}
更多信息见我的相关回答:
关于ios - 如何将核心数据模型项传递到 View 中进行编辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70643389/
Linux 有许多跨(假设是 2 个)CPU 内核执行的线程和进程。我希望我的单线程 C/C++ 应用程序成为 CPU0 上的唯一线程。我如何“移动”所有其他线程以使用 CPU1? 我知道我可以使用
我有一个类似于下图的数据库表 Table with 2 columns (UserId and value) 我将传递 UserId 和 2 个字符串。例如:userId: 1, key1: h1,
我想在我的新项目中使用 ASP.NET Core,因为我听说它更快。但是,该项目将使用广泛的数据库访问功能,Entity Framework Core 不支持其中一些功能。我想知道,是否可以使用 En
我已经使用 EntityFrameworkCore.SqlServer 2.0 开发了 asp .net core wep api 2.0 应用程序。它是使用数据库优先方法开发的。当尝试使用 dbco
我已经阅读了很多关于这个主题的文章,但我仍然无法处理这个问题。对不起,如果它是重复的,无论如何! 所以基本上,我正在从头开始构建一个 Angular 应用程序,并且我想按照最佳约定来组织我的代码。我有
我对MPI还是陌生的,所以如果这是一个琐碎的问题,请原谅我。我有一个四核CPU。我想运行一个在单个内核上使用两个进程的OpenMPI C++程序。有什么办法吗?如果是这样,那又如何?我提到了this
下面是一个传播异常处理机制的类问题,所需的输出是异常。任何人都可以解释为什么输出是异常,在此先感谢。 Class Question { public void m1() throws Excep
我想打印每个获得 CPU 时间片的进程的 name 和 pid。可能吗? 最佳答案 对于单个流程,您可以在以下位置获取此信息: /proc//stat 第14和第15个字段分别代表在用户态和内核态花费
我想知道是否可以识别具有特定 thread-id 的线程使用的物理处理器(核心)? 例如,我有一个多线程应用程序,它有两 (2) 个线程(例如,thread-id = 10 和 thread-id =
我有一个需要身份验证的 Solr 核心。假设我有一个用户,密码为password。当我现在尝试在控制台中创建一个 Solr 核心时 bin\solr create -c test 我收到 HTTP 错
我想为与使用它的项目不同的类库中的第二个和后续数据库创建迁移。有皱纹。我永远不会知道连接字符串,直到用户登录并且我可以从目录数据库 (saas) 中获取它。 对于目录数据库,我使用了来自 this 的
我想为一种可以产生 GHC Core 的简单语言创建一个前端。然后我想获取这个输出并通过正常的 GHC 管道运行它。根据this page , 不能直接通过 ghc 命令实现。我想知道是否有任何方法可
阅读文档,我构建了 2 个使用 BLE 连接 2 个 iDevices 的应用程序。 一个设备是中央设备,另一个是外围设备。 Central在寻找Peripheral,当找到它时,探索它的服务和特性,
在我的网络应用程序中,我对长时间运行的任务进行了操作,我想在后台调用此任务。因此,根据文档 .net core 3.1 Queued background tasks我为此使用这样的代码: publi
Solr 1.4 Enterprise Search Server 建议对核心副本进行大量更新,然后将其换成主核心。我正在按照以下步骤操作: 创建准备核心:http://localhost:8983/
它们是否存在,如果存在,文档和代码在哪里? 最佳答案 它们位于 Git 的 test 目录中。 https://github.com/jquery/jquery/tree/master/test 关于
我有一个 Lisp (SBCL 1.0.40.0.debian) 应用程序 (myfitnessdata),它使用以下代码来处理命令行参数: (:use :common-lisp) (:export
Core是GHC的中间语言。阅读Core可以帮助你更好地了解程序的性能。有人向我索要有关阅读 Core 的文档或教程,但我找不到太多。 有哪些文档可用于阅读 GHC Core? 这是我迄今为止发现的内
我有一个核心 WebJob 部署到 Azure Web 应用程序中。我正在使用WebJobs version 3.0.6 . 我注意到,WebJob 代码不会立即拾取对连接字符串和应用程序设置的更改(
我有一个在内部构造和使用 SqlConnection 类的第三方库。我可以从该类继承,但它有大量重载,到目前为止我一直无法找到合适的重载。我想要的是将参数附加到正在使用的连接字符串。 有没有办法在 .
我是一名优秀的程序员,十分优秀!