Swiftui 修改@FetchRequest

Swiftui 修改@FetchRequest,swiftui,Swiftui,Xcode beta 5为SwiftUI引入了@FetchRequest 我有一个视图,它有一个@FetchRequest。NSFetchRequest是在管理器中创建的,该管理器使属性包装器可以使用自身的静态实例(它们不能使用self)。相同的实例在创建时传递给视图 我想要的是在调用self.manager.reverse.toggle()时更新FetchRequest,以便视图更改其对象顺序。不幸的是,它似乎只调用了一次Manager.fetchRequest(),然后就再也不会调用了,即使

Xcode beta 5为SwiftUI引入了
@FetchRequest

我有一个视图,它有一个
@FetchRequest
NSFetchRequest
是在管理器中创建的,该管理器使属性包装器可以使用自身的静态实例(它们不能使用self)。相同的实例在创建时传递给视图

我想要的是在调用
self.manager.reverse.toggle()
时更新
FetchRequest
,以便视图更改其对象顺序。不幸的是,它似乎只调用了一次
Manager.fetchRequest()
,然后就再也不会调用了,即使在我创建新对象和在不同视图之间转换时也是如此

我正在寻找关于如何修改使用新属性包装器发出的获取请求的建议,以便根据用户操作使用我的对象

struct main视图:一些视图{
@观察对象变量管理器:管理器
@FetchRequest(FetchRequest:Manager.shared.FetchRequest())
var ts:FetchedResults
var body:一些观点{
导航视图{
列表(ts,id:\.self){t在
文本(t.name)
}
}.navigationBarItems(尾部:
按钮(操作:{
self.manager.reverse.toggle()
}){Text(“Reverse”)}
}
}
最终类管理器:ObservieObject{
@已发布变量反向:Bool=false
//因为属性包装器不能使用self,所以我们创建一个共享实例
//静态可用。此实例也提供给视图。
公共静态let shared=Manager()
func fetchRequest(反向:Bool=false)->NSFetchRequest{
let请求:NSFetchRequest=T.fetchRequest()
request.sortDescriptors=[
NSSortDescriptor(
键:“名称”,
升序:!self.reverse
)
]
退货申请
}
}

这是一个非常好的问题!我一直在尝试做这件事和其他类似的事情,但收效甚微。我真的希望这个问题能在即将到来的测试版中得到适当的解决。不过,在此期间,可以在两个@fetchrequest之间切换,以完成您希望完成的任务

下面是我正在使用的示例应用程序的工作代码。我使用一个按钮切换布尔@状态,然后使用该状态选择适当的@FetchResults。我不太喜欢它,但实际上它工作得很好

import SwiftUI
import CoreData

struct EntityListView : View {

    @Environment(\.editMode) var editMode

    @State var sortAscending: Bool = true

    @Environment(\.managedObjectContext) var context: NSManagedObjectContext

    @FetchRequest(entity: Entity.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Entity.order, ascending: true)])
    var ascendingEntities: FetchedResults<Entity>

    @FetchRequest(entity: Entity.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Entity.order, ascending: false)])
    var descendingEntities: FetchedResults<Entity>

    var body: some View {

        NavigationView {
            List() {
                Section(header: Text("All Entities".uppercased()))
                {
                    ForEach(sortAscending ? ascendingEntities : descendingEntities) { entity in

                            NavigationLink(destination: EntityEditView(entity: entity)) {

                                HStack {
                                    Text(entity.name)
                                        .font(.headline)
                                    Spacer()
                                    Text(String(entity.order))
                                        .font(.subheadline)
                                        .foregroundColor(.gray)
                                }
                            }
                            }
                            .onMove(perform: self.move)
                            .onDelete(perform: self.delete)
                }

                HStack {
                    Spacer()
                    Button(action: { self.sortAscending.toggle() }) { Text("Reverse Sort") }
                    Spacer()
                }
            }
            .listStyle(GroupedListStyle())
            .navigationBarTitle(Text("Entities"), displayMode: .large)
            .navigationBarItems(trailing: EditButton() )
        }
    }
}
导入快捷界面
导入CoreData
结构实体列表视图:视图{
@环境(\.editMode)变量editMode
@状态变量排序设置:Bool=true
@环境(\.managedObjectContext)变量上下文:NSManagedObjectContext
@FetchRequest(实体:entity.entity(),SortDescriptor:[NSSortDescriptor(键路径:\entity.order,升序:true)])
var ascendingEntities:获取的结果
@FetchRequest(实体:entity.entity(),SortDescriptor:[NSSortDescriptor(keyPath:\entity.order,升序:false)])
var下降属性:获取结果
var body:一些观点{
导航视图{
列表(){
节(标题:文本(“所有实体”.uppercased()))
{
ForEach(排序集?升序集:降序集){中的实体
导航链接(目标:EntityEditView(实体:实体)){
HStack{
文本(实体名称)
.font(.headline)
垫片()
文本(字符串(entity.order))
.font(.subheadline)
.foregroundColor(.灰色)
}
}
}
.onMove(执行:self.move)
.onDelete(执行:self.delete)
}
HStack{
垫片()
按钮(操作:{self.sortAscending.toggle()}{Text(“反向排序”)}
垫片()
}
}
.listStyle(GroupedListStyle())
.navigationBarTitle(文本(“实体”),显示模式:。大)
.navigationBarItems(尾部:EditButton())
}
}
}

SwiftUI使用不可变结构,这意味着无法更改获取请求属性。您需要将排序参数传递给struct init,从而在需要更改时创建一个全新的结构

我在这里学到了:

SwiftUI的视图应该是结构,这意味着它们是不可变的 如果这是我们自己的代码,我们可以使用 变异告诉斯威夫特他们会改变值,但我们不能这样做 在SwiftUI中,因为它使用计算属性


要解决您的问题,您应该将
MainView
包装在
SuperView
中。超级视图应该观察管理器。当管理器更改时,超级视图的主体将被调用并创建MainView的新实例。创建该实例时,您将获得一个新的@FeatchRequest

struct SuperView: some View {
    @ObservedObject var manager: Manager

    var body: some View {
       MainView()
    }
}

我希望它能工作,因为我还不能测试代码。

self.\u fetchedResults.update()
如果允许的话,可能会达到这个目的,但我无法使其可变,这是必需的:
不能在不可变值上使用mutating member:“self”是不可变的
查看FetchRequest的Beta 5 SwiftUI头,听起来像是update()在执行视图主体时调用,这将响应某些依赖状态的更改。FetchRequest似乎需要一个或多个新的初始值设定项,这些初始值设定项接受一个或多个到某个状态、环境等的绑定。希望在即将到来的beta版中会有更多的添加和更改。目前(beta 6),我已经放弃了“@FetchRequest”,直到它被大大的删除