Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Appendix 1: Core Data #12

Open
wants to merge 1 commit into
base: feature/L-9-location
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .gitignore
100644 → 100755
Empty file.
4 changes: 4 additions & 0 deletions DevAcademy.xcodeproj/project.pbxproj
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
84FA93B92A68319800DFC974 /* Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FA93B82A68319800DFC974 /* Properties.swift */; };
BE1E12592AA5C6CB000BA3D8 /* StoreadAsyncImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE1E12582AA5C6CB000BA3D8 /* StoreadAsyncImage.swift */; };
BE38A88A2AA7294400EB5431 /* UserLocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE38A8892AA7294400EB5431 /* UserLocationService.swift */; };
BE3DE9622AF3A83400F2028D /* CoreDataService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE3DE9612AF3A83400F2028D /* CoreDataService.swift */; };
BEEF9EC12A67C74E002126F4 /* PlacesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEEF9EC02A67C74E002126F4 /* PlacesService.swift */; };
C05610492A5C78CA007FB970 /* DevAcademyApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05610482A5C78CA007FB970 /* DevAcademyApp.swift */; };
C056104B2A5C78CA007FB970 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C056104A2A5C78CA007FB970 /* RootView.swift */; };
Expand Down Expand Up @@ -47,6 +48,7 @@
BE1E12582AA5C6CB000BA3D8 /* StoreadAsyncImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreadAsyncImage.swift; sourceTree = "<group>"; };
BE38A8882AA7285B00EB5431 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
BE38A8892AA7294400EB5431 /* UserLocationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserLocationService.swift; sourceTree = "<group>"; };
BE3DE9612AF3A83400F2028D /* CoreDataService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataService.swift; sourceTree = "<group>"; };
BEEF9EC02A67C74E002126F4 /* PlacesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacesService.swift; sourceTree = "<group>"; };
C05610452A5C78CA007FB970 /* DevAcademy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DevAcademy.app; sourceTree = BUILT_PRODUCTS_DIR; };
C05610482A5C78CA007FB970 /* DevAcademyApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevAcademyApp.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -114,6 +116,7 @@
C0B74A2E2A8280D80018D10F /* Services.swift */,
BEEF9EC02A67C74E002126F4 /* PlacesService.swift */,
BE38A8892AA7294400EB5431 /* UserLocationService.swift */,
BE3DE9612AF3A83400F2028D /* CoreDataService.swift */,
);
path = Services;
sourceTree = "<group>";
Expand Down Expand Up @@ -286,6 +289,7 @@
84FA93B12A68313E00DFC974 /* PossibleKind.swift in Sources */,
C0CAEACB2A80220A008D87C2 /* Coordinator.swift in Sources */,
C0B74A2D2A8280C60018D10F /* ObservableObjects.swift in Sources */,
BE3DE9622AF3A83400F2028D /* CoreDataService.swift in Sources */,
BE1E12592AA5C6CB000BA3D8 /* StoreadAsyncImage.swift in Sources */,
84FA93B72A68317F00DFC974 /* Point.swift in Sources */,
C056104B2A5C78CA007FB970 /* RootView.swift in Sources */,
Expand Down
Empty file.
Empty file.
Empty file.
Empty file modified DevAcademy.xcodeproj/xcshareddata/xcschemes/DevAcademy.xcscheme
100644 → 100755
Empty file.
Empty file modified DevAcademy/Assets.xcassets/AccentColor.colorset/Contents.json
100644 → 100755
Empty file.
Empty file modified DevAcademy/Assets.xcassets/AppIcon.appiconset/Contents.json
100644 → 100755
Empty file.
Empty file modified DevAcademy/Assets.xcassets/Contents.json
100644 → 100755
Empty file.
Empty file modified DevAcademy/DevAcademyApp.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Environment/Coordinator.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Environment/Environment.swift
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion DevAcademy/Environment/ObservableObjects.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class ObservableObjects {

extension ObservableObjects {
convenience init(services: Services) {
let places = PlacesObservableObject(placesService: services.placesService, locationService: services.locationService)
let places = PlacesObservableObject(placesService: services.placesService, locationService: services.locationService, coreDataService: services.coreDataService)

self.init(
places: places
Expand Down
40 changes: 25 additions & 15 deletions DevAcademy/Environment/ObservableObjects/PlacesObservableObject.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ import CoreLocation

final class PlacesObservableObject: ObservableObject {
@Published var places: [Place] = []

private(set) var favouritePlaces: [Int]? {
get { UserDefaults.standard.array(forKey: "favourites") as? [Int] }
set {
UserDefaults.standard.set(newValue, forKey: "favourites")
updatePlaces()
}
}

private var rawPlaces: [Place] = [] {
didSet { updatePlaces() }
}
private let placesService: PlacesService
private let locationService: UserLocationService
private let coreDataService: CoreDataService
private var lastUpdatedLocation: CLLocation?


init(placesService: PlacesService, locationService: UserLocationService) {
init(placesService: PlacesService, locationService: UserLocationService, coreDataService: CoreDataService) {
self.placesService = placesService
self.locationService = locationService
self.coreDataService = coreDataService

self.locationService.listenDidUpdateLocation { [weak self] location in
DispatchQueue.main.async {
Expand All @@ -40,11 +42,11 @@ final class PlacesObservableObject: ObservableObject {
}
}
}

func set(place: Place, favourite setFavourite: Bool) {
var favouritePlaces = self.favouritePlaces ?? []
let currentIndex = favouritePlaces.firstIndex(of: place.attributes.ogcFid)

switch (setFavourite, currentIndex) {
case (true, nil):
favouritePlaces.append(place.attributes.ogcFid)
Expand All @@ -53,10 +55,10 @@ final class PlacesObservableObject: ObservableObject {
default:
return
}

self.favouritePlaces = favouritePlaces
}

// A. Closure variant
func fetchPlaces() {
placesService.places { result in
Expand All @@ -70,7 +72,7 @@ final class PlacesObservableObject: ObservableObject {
}
}
}

// B. Async with checked continuation variant
func fetchPlacesWithCheckedContinuation() async {
let result = await placesService.placesWithCheckedContinuation()
Expand All @@ -83,7 +85,7 @@ final class PlacesObservableObject: ObservableObject {
print(error)
}
}

// C. Async variant
@MainActor
func fetchPlacesWithAsync() async {
Expand All @@ -94,7 +96,7 @@ final class PlacesObservableObject: ObservableObject {
print(error)
}
}

private func updatePlaces() {
var regularPlaces = rawPlaces

Expand All @@ -106,14 +108,14 @@ final class PlacesObservableObject: ObservableObject {
guard let lPoint = lPlace.geometry?.cllocation else {
return true
}

return lastUpdatedLocation.distance(from: lPoint).magnitude < lastUpdatedLocation.distance(from: rPoint).magnitude
}
}

var presentOnTop: [Place] = []
let favouritePlaces = self.favouritePlaces ?? []

regularPlaces.removeAll { place in
if favouritePlaces.contains(place.attributes.ogcFid) {
presentOnTop.append(place)
Expand All @@ -122,7 +124,7 @@ final class PlacesObservableObject: ObservableObject {
return false
}
}

self.places = presentOnTop + regularPlaces
}

Expand All @@ -139,4 +141,12 @@ final class PlacesObservableObject: ObservableObject {
self.lastUpdatedLocation = userLocation
updatePlaces()
}

func loadNote(forPlace ogcFid: Int) -> String? {
coreDataService.loadNote(forPlace: ogcFid)
}

func save(note: String?, forPlace ogcFid: Int) {
coreDataService.save(note: note, forPlace: ogcFid)
}
}
Empty file modified DevAcademy/Info.plist
100644 → 100755
Empty file.
Empty file modified DevAcademy/Library/Views/MapView.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Library/Views/StoreadAsyncImage.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Model/IdentifiableCoordinate.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Model/Kind.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Model/Place.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Model/Places.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Model/Point.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Model/PossibleKind.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Model/Properties.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/RootView.swift
100644 → 100755
Empty file.
14 changes: 14 additions & 0 deletions DevAcademy/Scenes/PlaceDetail/PlaceDetailView.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ struct PlaceDetailView: View {
let state: PlaceDetailViewState

var body: some View {
TextEditor(text: .init(
get: { state.note ?? "" },
set: { state.note = $0 })
)
.foregroundColor(Color.gray)
.border(Color.red)
ScrollView {
VStack {
HStack(alignment: .center) {
Expand All @@ -21,6 +27,8 @@ struct PlaceDetailView: View {
}
}
.padding([.horizontal, .bottom])


if let placeImageUrl = state.placeImageUrl {
AsyncImage(url: placeImageUrl) { image in
image
Expand Down Expand Up @@ -49,6 +57,12 @@ struct PlaceDetailView: View {
}
.navigationTitle(state.placeTitle)
}
.onAppear {
state.loadNote()
}
.onDisappear {
state.saveNoteState()
}
}
}

Expand Down
11 changes: 10 additions & 1 deletion DevAcademy/Scenes/PlaceDetail/PlaceDetailViewState.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import MapKit

struct PlaceDetailViewState: DynamicProperty {
@EnvironmentObject private var placesObject: PlacesObservableObject

@State var note: String? = nil

private let place: Place

init(place: Place) {
Expand Down Expand Up @@ -36,5 +37,13 @@ struct PlaceDetailViewState: DynamicProperty {
}
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}

func loadNote() {
note = placesObject.loadNote(forPlace: place.attributes.ogcFid)
}

func saveNoteState() {
placesObject.save(note: note, forPlace: place.attributes.ogcFid)
}
}

Empty file modified DevAcademy/Scenes/Places/PlaceRow.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Scenes/Places/PlacesView.swift
100644 → 100755
Empty file.
Empty file modified DevAcademy/Scenes/Places/PlacesViewState.swift
100644 → 100755
Empty file.
27 changes: 27 additions & 0 deletions DevAcademy/Services/CoreDataService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// CoreDataService.swift
// DevAcademy
//
// Created by Mikoláš Stuchlík on 02.11.2023.
//

import CoreData

protocol CoreDataService {
func loadNote(forPlace ogcFid: Int) -> String?
func save(note: String?, forPlace ogcFid: Int)
}

final class ProductionsCoreDataService: NSObject, CoreDataService {
func loadNote(forPlace ogcFid: Int) -> String? {
nil
}

func save(note: String?, forPlace ogcFid: Int) {
}
}

final class MockCoreDataService: CoreDataService {
func loadNote(forPlace ogcFid: Int) -> String? { nil }
func save(note: String?, forPlace ogcFid: Int) { }
}
Empty file modified DevAcademy/Services/PlacesService.swift
100644 → 100755
Empty file.
12 changes: 9 additions & 3 deletions DevAcademy/Services/Services.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,29 @@ import Foundation
final class Services {
let placesService: PlacesService
let locationService: UserLocationService
let coreDataService: CoreDataService

init(
placesService: PlacesService,
locationService: UserLocationService
locationService: UserLocationService,
coreDateService: CoreDataService
) {
self.placesService = placesService
self.locationService = locationService
self.coreDataService = coreDateService
}
}

extension Services {
convenience init() {
let placesService = ProductionPlacesService()
let locationService = ProductionUserLocationService()
let coreDataService = ProductionsCoreDataService()

self.init(
placesService: placesService,
locationService: locationService
locationService: locationService,
coreDateService: coreDataService
)
}
}
Expand All @@ -30,6 +35,7 @@ extension Services {
extension Services {
static let mock = Services(
placesService: MockPlacesService(),
locationService: MockLocationService()
locationService: MockLocationService(),
coreDateService: MockCoreDataService()
)
}
Empty file modified DevAcademy/Services/UserLocationService.swift
100644 → 100755
Empty file.
Empty file modified README.md
100644 → 100755
Empty file.
Empty file modified doc/l9assignment.md
100644 → 100755
Empty file.