Move towards having views be initialized with a view model.
- As opposed to being responsible for initializing their own.
This commit is contained in:
parent
1a183b2f7b
commit
ddb4f20990
|
@ -13,12 +13,7 @@ struct EditLocationView: View {
|
|||
@Environment(\.presentationMode) var presentationMode
|
||||
@EnvironmentObject var store: AppStore
|
||||
|
||||
@ObservedObject private(set) var viewModel: EditLocationViewModel
|
||||
|
||||
|
||||
init(location: Location) {
|
||||
self.viewModel = EditLocationViewModel(location: location)
|
||||
}
|
||||
@ObservedObject var viewModel: EditLocationViewModel
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,12 +23,47 @@ extension EditLocationView {
|
|||
var body: some View {
|
||||
NavigationView {
|
||||
Form {
|
||||
Section {
|
||||
TextField("Location Name", text: Binding($viewModel.location.title, "Untitled Location"))
|
||||
// TextField("Description", text: Binding($viewModel.location.longDescription, ""))
|
||||
TextField("Description", text: Binding($viewModel.location.longDescription, replacingNilWith: ""))
|
||||
Section(header: Text("Details").font(.headline)) {
|
||||
TextField(
|
||||
"Location Name",
|
||||
text: Binding($viewModel.location.title, "Untitled Location")
|
||||
)
|
||||
TextField(
|
||||
"Description",
|
||||
text: Binding($viewModel.location.longDescription, replacingNilWith: "")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Section(header: Text("Add A Photo").font(.headline)) {
|
||||
|
||||
Button(action: {
|
||||
|
||||
}) {
|
||||
Group {
|
||||
// if viewModel.location.userPhoto != nil {
|
||||
if false {
|
||||
} else {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
VStack {
|
||||
Image(systemName: "camera")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 120)
|
||||
|
||||
Text("No Photo Selected")
|
||||
.font(.title)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: 200)
|
||||
}
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
}
|
||||
.padding(.bottom)
|
||||
|
||||
|
||||
Section(header: Text("Nearby Locations...").font(.headline)) {
|
||||
|
@ -52,8 +82,6 @@ extension EditLocationView {
|
|||
.navigationBarItems(trailing: saveButton)
|
||||
}
|
||||
.onAppear {
|
||||
self.viewModel.store = self.store
|
||||
|
||||
self.store.send(.wikiPages(.fetchStateSet(.fetching)))
|
||||
self.store.send(WikiPagesSideEffect.fetchPages(near: self.viewModel.location))
|
||||
}
|
||||
|
@ -87,7 +115,10 @@ struct EditLocationView_Previews: PreviewProvider {
|
|||
|
||||
static var previews: some View {
|
||||
EditLocationView(
|
||||
location: SampleData.Locations.santorini
|
||||
viewModel: EditLocationViewModel(
|
||||
location: SampleData.Locations.santorini,
|
||||
wikiPagesState: SampleData.SampleAppStore.default.state.wikiPagesState
|
||||
)
|
||||
)
|
||||
.environment(\.managedObjectContext, CurrentApp.coreDataManager.mainContext)
|
||||
.environmentObject(SampleData.SampleAppStore.default)
|
||||
|
|
|
@ -14,23 +14,24 @@ import Combine
|
|||
final class EditLocationViewModel: ObservableObject {
|
||||
private var subscriptions = Set<AnyCancellable>()
|
||||
|
||||
var store: AppStore! {
|
||||
didSet {
|
||||
guard store != nil else { return }
|
||||
self.setupSubscribers()
|
||||
}
|
||||
}
|
||||
|
||||
@ObservedObject var location: Location
|
||||
private let wikiPagesState: WikiPagesState
|
||||
|
||||
|
||||
init(location: Location) {
|
||||
self.location = location
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Published Outputs
|
||||
@Published var wikiPagesFetchState: WikiPagesState.FetchState = .inactive
|
||||
|
||||
|
||||
// MARK: - Init
|
||||
init(
|
||||
location: Location,
|
||||
wikiPagesState: WikiPagesState
|
||||
) {
|
||||
self.location = location
|
||||
self.wikiPagesState = wikiPagesState
|
||||
|
||||
setupSubscribers()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,8 +39,7 @@ final class EditLocationViewModel: ObservableObject {
|
|||
extension EditLocationViewModel {
|
||||
|
||||
private var wikiPagesFetchStatePublisher: AnyPublisher<WikiPagesState.FetchState, Never> {
|
||||
store.$state
|
||||
.map(\.wikiPagesState.currentFetchState)
|
||||
CurrentValueSubject(wikiPagesState.currentFetchState)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,17 +13,12 @@ import MapKit
|
|||
struct LocationCollectionView: View {
|
||||
@EnvironmentObject var store: AppStore
|
||||
|
||||
@ObservedObject private(set) var viewModel: LocationCollectionViewModel
|
||||
@ObservedObject var viewModel: LocationCollectionViewModel
|
||||
|
||||
@State private var centerCoordinate = CLLocationCoordinate2D()
|
||||
@State var selectedLocation: Location? = nil
|
||||
@State private var isShowingEditView = false
|
||||
@State private var isShowingSelectedLocationAlert = false
|
||||
|
||||
|
||||
init(collection: LocationCollection) {
|
||||
self.viewModel = LocationCollectionViewModel(collection: collection)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,8 +44,13 @@ extension LocationCollectionView {
|
|||
}
|
||||
) {
|
||||
if self.selectedLocation != nil {
|
||||
EditLocationView(location: self.selectedLocation!)
|
||||
.environmentObject(self.store)
|
||||
EditLocationView(
|
||||
viewModel: EditLocationViewModel(
|
||||
location: self.selectedLocation!,
|
||||
wikiPagesState: self.store.state.wikiPagesState
|
||||
)
|
||||
)
|
||||
.environmentObject(self.store)
|
||||
} else {
|
||||
Text("No Location found for editing")
|
||||
}
|
||||
|
@ -59,14 +59,14 @@ extension LocationCollectionView {
|
|||
Alert(
|
||||
title: Text(selectedLocation?.title ?? "Undisclosed Location"),
|
||||
message: Text(selectedLocation?.longDescription ?? "No description has been provided yet."),
|
||||
primaryButton: .default(Text("Edit"), action: {
|
||||
self.isShowingEditView = true
|
||||
}),
|
||||
primaryButton: .default(
|
||||
Text("Edit"),
|
||||
action: { self.isShowingEditView = true }
|
||||
),
|
||||
secondaryButton: .cancel(Text("OK"))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,7 +152,9 @@ private extension LocationCollectionView {
|
|||
struct LocationCollectionView_Previews: PreviewProvider {
|
||||
|
||||
static var previews: some View {
|
||||
LocationCollectionView(collection: SampleData.LocationCollections.default)
|
||||
.environmentObject(SampleData.SampleAppStore.default)
|
||||
LocationCollectionView(
|
||||
viewModel: LocationCollectionViewModel(collection: SampleData.LocationCollections.default)
|
||||
)
|
||||
.environmentObject(SampleData.SampleAppStore.default)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,13 +20,6 @@ final class LocationCollectionViewModel: NSObject, ObservableObject {
|
|||
|
||||
// MARK: - Published Outputs
|
||||
@Published var locations: [Location] = []
|
||||
@Published var isShowingEditView: Bool = false
|
||||
|
||||
@Published var isShowingSelectedLocationAlert: Bool = false {
|
||||
didSet {
|
||||
print("isShowingSelectedLocationAlert - didSet: \(isShowingSelectedLocationAlert)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Init
|
||||
|
@ -34,9 +27,6 @@ final class LocationCollectionViewModel: NSObject, ObservableObject {
|
|||
self.collection = collection
|
||||
|
||||
super.init()
|
||||
|
||||
// self.fetchedResultsController.delegate = self
|
||||
// fetchLocations()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ extension LocationCollectionsContainerView {
|
|||
Group {
|
||||
if viewModel.isAuthenticated {
|
||||
LocationCollectionsListView(
|
||||
buildDestination: LocationCollectionView.init(collection:)
|
||||
buildDestination: LocationCollectionsContainerViewModel.destination(for:)
|
||||
)
|
||||
} else {
|
||||
authenticationNotice
|
||||
|
@ -83,6 +83,16 @@ extension LocationCollectionsContainerView {
|
|||
}
|
||||
|
||||
|
||||
private extension LocationCollectionsContainerView {
|
||||
|
||||
func destination(for locationCollection: LocationCollection) -> LocationCollectionView {
|
||||
let viewModel = LocationCollectionViewModel(collection: locationCollection)
|
||||
|
||||
return LocationCollectionView(viewModel: viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: - Preview
|
||||
struct LocationCollectionsContainerView_Previews: PreviewProvider {
|
||||
|
|
|
@ -64,9 +64,17 @@ extension LocationCollectionsContainerViewModel {
|
|||
)
|
||||
.store(in: &subscriptions)
|
||||
}
|
||||
|
||||
|
||||
static func destination(for locationCollection: LocationCollection) -> LocationCollectionView {
|
||||
let viewModel = LocationCollectionViewModel(collection: locationCollection)
|
||||
|
||||
return .init(viewModel: viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Computed
|
||||
|
||||
// MARK: - Computeds
|
||||
extension LocationCollectionsContainerViewModel {
|
||||
|
||||
var authenticationErrorAlertTitle: String { "Authentication Failed" }
|
||||
|
|
Loading…
Reference in New Issue