use @StateObject when the view owns the observable object

This commit is contained in:
Satindar Dhillon 2022-02-26 10:54:05 -08:00
parent de07e9ad92
commit 1073c63476
9 changed files with 55 additions and 44 deletions

View file

@ -95,10 +95,10 @@ final class ShareExtensionViewModel: ObservableObject {
}
struct ShareExtensionView: View {
@ObservedObject private var viewModel: ShareExtensionViewModel
@StateObject private var viewModel: ShareExtensionViewModel
init(extensionContext: NSExtensionContext?) {
self.viewModel = ShareExtensionViewModel(extensionContext: extensionContext)
self._viewModel = StateObject(wrappedValue: ShareExtensionViewModel(extensionContext: extensionContext))
}
var body: some View {

View file

@ -22,8 +22,18 @@ public final class RootViewModel: ObservableObject {
public var subscriptions = Set<AnyCancellable>()
public init() {
public init(pdfViewerProvider: ((URL, PDFViewerViewModel) -> AnyView)?) {
registerFonts()
if let pdfViewerProvider = pdfViewerProvider {
configurePDFProvider(pdfViewerProvider: pdfViewerProvider)
}
#if DEBUG
if CommandLine.arguments.contains("--uitesting") {
services.authenticator.logout()
}
#endif
}
func configurePDFProvider(pdfViewerProvider: @escaping (URL, PDFViewerViewModel) -> AnyView) {
@ -112,26 +122,13 @@ private struct SafariWebLinkPath: Identifiable {
}
public struct RootView: View {
@ObservedObject private var viewModel: RootViewModel
@ObservedObject private var authenticator: Authenticator
@StateObject private var viewModel: RootViewModel
public init(
pdfViewerProvider: ((URL, PDFViewerViewModel) -> AnyView)?,
intercomProvider: IntercomProvider?
) {
let rootViewModel = RootViewModel()
self.viewModel = rootViewModel
self.authenticator = rootViewModel.services.authenticator
#if DEBUG
if CommandLine.arguments.contains("--uitesting") {
authenticator.logout()
}
#endif
if let pdfViewerProvider = pdfViewerProvider {
viewModel.configurePDFProvider(pdfViewerProvider: pdfViewerProvider)
}
self._viewModel = StateObject(wrappedValue: RootViewModel(pdfViewerProvider: pdfViewerProvider))
if let intercomProvider = intercomProvider {
DataService.showIntercomMessenger = intercomProvider.showIntercomMessenger
@ -141,7 +138,7 @@ public struct RootView: View {
}
@ViewBuilder private var innerBody: some View {
if authenticator.isLoggedIn {
if viewModel.services.authenticator.isLoggedIn {
PrimaryContentView()
.onAppear {
viewModel.triggerPushNotificationRequestIfNeeded()

View file

@ -101,13 +101,15 @@ final class CreateProfileViewModel: ObservableObject {
struct CreateProfileContainerView: View {
@EnvironmentObject var authenticator: Authenticator
@EnvironmentObject var dataService: DataService
@ObservedObject private var viewModel: CreateProfileViewModel
@StateObject private var viewModel: CreateProfileViewModel
@State private var name: String
@State private var bio = ""
init(userProfile: UserProfile, dataService: DataService) {
self.viewModel = CreateProfileViewModel(initialUserProfile: userProfile, dataService: dataService)
self._viewModel = StateObject(
wrappedValue: CreateProfileViewModel(initialUserProfile: userProfile, dataService: dataService)
)
self._name = State(initialValue: userProfile.name)
}

View file

@ -179,7 +179,7 @@ final class HomeFeedViewModel: ObservableObject {
struct HomeFeedView: View {
@EnvironmentObject var dataService: DataService
@ObservedObject private var viewModel = HomeFeedViewModel()
@StateObject private var viewModel = HomeFeedViewModel()
@State private var selectedLinkItem: FeedItem?
@State private var searchQuery = ""
@State private var itemToRemove: FeedItem?

View file

@ -30,12 +30,12 @@ final class NewAppleSignupViewModel: ObservableObject {
struct NewAppleSignupView: View {
@EnvironmentObject var authenticator: Authenticator
@ObservedObject private var viewModel: NewAppleSignupViewModel
@StateObject private var viewModel: NewAppleSignupViewModel
let showProfileEditView: () -> Void
init(userProfile: UserProfile, showProfileEditView: @escaping () -> Void) {
self.showProfileEditView = showProfileEditView
self.viewModel = NewAppleSignupViewModel(userProfile: userProfile)
self._viewModel = StateObject(wrappedValue: NewAppleSignupViewModel(userProfile: userProfile))
}
var body: some View {

View file

@ -43,7 +43,7 @@ final class NewsletterEmailsViewModel: ObservableObject {
struct NewsletterEmailsView: View {
@EnvironmentObject var dataService: DataService
@ObservedObject var viewModel = NewsletterEmailsViewModel()
@StateObject var viewModel = NewsletterEmailsViewModel()
let footerText = "Add PDFs to your library, or subscribe to emails using an Omnivore email address."
var body: some View {

View file

@ -30,7 +30,7 @@ struct ProfileView: View {
@EnvironmentObject var authenticator: Authenticator
@EnvironmentObject var dataService: DataService
@ObservedObject private var viewModel = ProfileContainerViewModel()
@StateObject private var viewModel = ProfileContainerViewModel()
@State private var showLogoutConfirmation = false

View file

@ -88,7 +88,7 @@ struct RegistrationView: View {
@EnvironmentObject var authenticator: Authenticator
@EnvironmentObject var dataService: DataService
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@ObservedObject private var viewModel = RegistrationViewModel()
@StateObject private var viewModel = RegistrationViewModel()
var authenticationView: some View {
VStack(spacing: 0) {

View file

@ -5,31 +5,43 @@ import Utils
struct AsyncImage: View {
let isResizable: Bool
@ObservedObject private var imageLoader = ImageLoader()
let url: URL?
@State private var isLoaded = false
@StateObject private var imageLoader = ImageLoader()
init(url: URL?, isResizable: Bool = true) {
self.isResizable = isResizable
if let url = url {
self.url = url
}
func load() {
if let url = url, !isLoaded {
imageLoader.load(fromUrl: url)
isLoaded = true
}
}
var body: some View {
#if os(iOS)
if isResizable {
Image(uiImage: imageLoader.image ?? imageLoader.placeholder)
.resizable()
} else {
Image(uiImage: imageLoader.image ?? imageLoader.placeholder)
}
#elseif os(macOS)
if isResizable {
Image(nsImage: imageLoader.image ?? imageLoader.placeholder)
.resizable()
} else {
Image(nsImage: imageLoader.image ?? imageLoader.placeholder)
}
#endif
Group {
#if os(iOS)
if isResizable {
Image(uiImage: imageLoader.image ?? imageLoader.placeholder)
.resizable()
} else {
Image(uiImage: imageLoader.image ?? imageLoader.placeholder)
}
#elseif os(macOS)
if isResizable {
Image(nsImage: imageLoader.image ?? imageLoader.placeholder)
.resizable()
} else {
Image(nsImage: imageLoader.image ?? imageLoader.placeholder)
}
#endif
}
.onAppear {
load()
}
}
}