如何使用nsmanagedObject在Swiftui中重复使用同一功能
假设我们有一个主视图mainview
和一个子查看loginview
哪些执行用户登录功能。我选择了Coredata来存储一些持久的数据,例如用户名和密码以及@State
in mainView
以存储非固定数据(例如登录状态)。
当用户打开应用程序时,我还想支持自动登录。因此,loginview
中的登录函数也在mainView
中使用。我的演示代码在下面粘贴。
import SwiftUI
import CoreData
struct MainView: View {
@State private var loggingIn: Bool = false
@State private var token: String? = nil
// `UserInfo` here is a `NSManagedObject` fetched from CoreData
@ObservedObject private var info: UserInfo
init() {
// fetch info from CoreData
}
func logIn() {
await MainActor.run {
self.loggingIn = true
}
let token = await performLoginHttpRequest(cred.username!, cred.password!)
await MainActor.run {
self.loggingIn = false
self.token = token
}
}
var body: some View {
NavigationView {
VStack {
if logging {
ProgressView()
} else if token == nil {
Text("Logged Out")
} else {
Text("Token: \(token!)")
}
NavigationLink("Login") {
LoginView(info: info, logging: $loggingIn)
}
}
}
.task {
await logIn()
}
}
}
struct LoginView: View {
@ObservedObject var info: UserInfo
@Binding var loggingIn: Bool
@Binding var token: String?
func logIn() async {
// basically same as in MainView, but
// `loggingIn` and `token` here is wrapped
// with `@Binding`
}
var body: some View {
// UI to login
}
}
如您所见,这里的问题是我必须在mainView
和loginview
中编写相同的逻辑,因为我不知道如何在这种配置中共享逻辑。
我尝试了一些丑陋的解决方法,例如将userInfo
包装在另一个observableObject
中并在视图之间共享。但是嵌套的可观察到
在SwiftUI中似乎不建议使用。有什么优雅的方法可以实施吗?
Suppose we have a main view MainView
and a child view LoginView
which perform login function for user. I have chosen CoreData to store some persisted data like username and password and @State
in MainView
to store non-persisted data like logging-in status.
I also want to support automatic login when the user opens the app. So the login function in LoginView
is also used in MainView
. My demo code is pasted below.
import SwiftUI
import CoreData
struct MainView: View {
@State private var loggingIn: Bool = false
@State private var token: String? = nil
// `UserInfo` here is a `NSManagedObject` fetched from CoreData
@ObservedObject private var info: UserInfo
init() {
// fetch info from CoreData
}
func logIn() {
await MainActor.run {
self.loggingIn = true
}
let token = await performLoginHttpRequest(cred.username!, cred.password!)
await MainActor.run {
self.loggingIn = false
self.token = token
}
}
var body: some View {
NavigationView {
VStack {
if logging {
ProgressView()
} else if token == nil {
Text("Logged Out")
} else {
Text("Token: \(token!)")
}
NavigationLink("Login") {
LoginView(info: info, logging: $loggingIn)
}
}
}
.task {
await logIn()
}
}
}
struct LoginView: View {
@ObservedObject var info: UserInfo
@Binding var loggingIn: Bool
@Binding var token: String?
func logIn() async {
// basically same as in MainView, but
// `loggingIn` and `token` here is wrapped
// with `@Binding`
}
var body: some View {
// UI to login
}
}
As you can see, the problem here is that I have to write the same logic in MainView
and LoginView
since I do not know how to share the logic in such configuration.
I have tried some ugly workaround like wrapping the UserInfo
in another ObservableObject
and sharing it between views. But nested ObservableObject
seems not recommended in SwiftUI. Is there any elegant way to implement this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论