Skip to content

Commit

Permalink
Merge pull request #31 from OneBusAway/Issue-22-origin-destinaton_bas…
Browse files Browse the repository at this point in the history
…ed_on_map

Issue 22 - Origin Destinatoin Map Marker
  • Loading branch information
aaronbrethorst authored Jul 18, 2024
2 parents dd2b683 + ec834de commit 4f79722
Show file tree
Hide file tree
Showing 25 changed files with 90 additions and 42 deletions.
2 changes: 0 additions & 2 deletions OTPKit/Features/OriginDestination/OriginDestinationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ public struct OriginDestinationView: View {
.frame(height: 135)
.scrollContentBackground(.hidden)
.scrollDisabled(true)

Spacer()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public struct AddFavoriteLocationsSheet: View {
.padding(.horizontal, 16)

List {
if search.isEmpty, let userLocation = userLocation {
if search.isEmpty, let userLocation {
Button(action: {
switch UserDefaultsServices.shared.saveFavoriteLocationData(data: userLocation) {
case .success:
Expand Down Expand Up @@ -110,7 +110,7 @@ public struct AddFavoriteLocationsSheet: View {
})
}
}
.onChange(of: search) { searchValue in
.onChange(of: search) { _, searchValue in
locationService.update(queryFragment: searchValue)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ public struct OriginDestinationSheetView: View {
// swiftlint:enable function_body_length
private func recentsSection() -> some View {
if sheetEnvironment.recentLocations.isEmpty {
return AnyView(EmptyView())
AnyView(EmptyView())
} else {
return AnyView(
AnyView(
Section(content: {
ForEach(Array(sheetEnvironment.recentLocations.prefix(5)), content: { location in
VStack(alignment: .leading) {
Expand Down Expand Up @@ -190,7 +190,7 @@ public struct OriginDestinationSheetView: View {

private func currentUserSection() -> some View {
Group {
if let userLocation = userLocation {
if let userLocation {
Button(action: {
switch UserDefaultsServices.shared.saveRecentLocations(data: userLocation) {
case .success:
Expand Down Expand Up @@ -222,7 +222,7 @@ public struct OriginDestinationSheetView: View {
.padding(.horizontal, 16)

List {
if search.isEmpty && isSearchFocused {
if search.isEmpty, isSearchFocused {
currentUserSection()
} else if search.isEmpty {
favoritesSection()
Expand All @@ -231,12 +231,9 @@ public struct OriginDestinationSheetView: View {
searchResultsSection()
}
}
.onChange(of: search) { searchValue in
.onChange(of: search) { _, searchValue in
locationService.update(queryFragment: searchValue)
}
.onChange(of: isSearchFocused) { value in
print(value)
}

Spacer()
}
Expand Down
14 changes: 14 additions & 0 deletions OTPKit/Models/MapExtension/MarkerItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// MarkerItem.swift
// OTPKit
//
// Created by Hilmy Veradin on 16/07/24.
//

import Foundation
import MapKit

public struct MarkerItem: Identifiable, Hashable {
public let id: UUID = .init()
public let item: MKMapItem
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions OTPKit/Services/LocationServices.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
import MapKit

/// LocationService is the main class that's responsible for managing MKLocalSearchCompleter
/// Manages everything location such as search completer, etc
public final class LocationService: NSObject, ObservableObject, MKLocalSearchCompleterDelegate {
private let completer: MKLocalSearchCompleter

Expand Down Expand Up @@ -51,8 +51,8 @@ public final class LocationService: NSObject, ObservableObject, MKLocalSearchCom
let search = MKLocalSearch(request: searchRequest)

search.start { [weak self] response, error in
guard let self = self, let response = response else {
if let error = error {
guard let self, let response else {
if let error {
print("Error performing local search: \(error)")
}
return
Expand Down
30 changes: 30 additions & 0 deletions OTPKit/Services/MapExtensionServices.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// MapExtensionServices.swift
// OTPKit
//
// Created by Hilmy Veradin on 16/07/24.
//

import Foundation
import MapKit
import SwiftUI

/// Manage Map extension such as markers, etc
public final class MapExtensionServices: ObservableObject {
public static let shared = MapExtensionServices()

@Published public var selectedMapPoint: [MarkerItem] = []

public func appendMarker(coordinate: CLLocationCoordinate2D) {
let mapItem = MKMapItem(placemark: .init(coordinate: coordinate))
let markerItem = MarkerItem(item: mapItem)
selectedMapPoint.append(markerItem)
}

/// Generate MapKit Marker View
public func generateMarkers() -> ForEach<[MarkerItem], MarkerItem.ID, Marker<Text>> {
ForEach(selectedMapPoint, id: \.id) { markerItem in
Marker(item: markerItem.item)
}
}
}
18 changes: 7 additions & 11 deletions OTPKit/Services/UserDefaultsServices.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

/// Main database of OTPKit Demo
/// Manages data persistance
/// Each CRUD features divided by `MARK` comment
public final class UserDefaultsServices {
public static let shared = UserDefaultsServices()
Expand Down Expand Up @@ -35,13 +35,11 @@ public final class UserDefaultsServices {
}

func saveFavoriteLocationData(data: Location) -> Result<Void, Error> {
var locations: [Location]

switch getFavoriteLocationsData() {
var locations: [Location] = switch getFavoriteLocationsData() {
case let .success(existingLocations):
locations = existingLocations
existingLocations
case .failure:
locations = []
[]
}

locations.append(data)
Expand Down Expand Up @@ -98,13 +96,11 @@ public final class UserDefaultsServices {
}

func saveRecentLocations(data: Location) -> Result<Void, Error> {
var locations: [Location]

switch getFavoriteLocationsData() {
var locations: [Location] = switch getFavoriteLocationsData() {
case let .success(existingLocations):
locations = existingLocations
existingLocations
case .failure:
locations = []
[]
}

locations.insert(data, at: 0)
Expand Down
2 changes: 1 addition & 1 deletion OTPKit/Services/UserLocationServices.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
import MapKit

/// `UserLocationServices` responsible for asking permission, and manage current users location
/// Manages permission, and current users location
public final class UserLocationServices: NSObject, ObservableObject, CLLocationManagerDelegate {
@Published var currentLocation: Location?

Expand Down
33 changes: 23 additions & 10 deletions OTPKitDemo/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,40 @@ import SwiftUI
public struct MapView: View {
@StateObject private var sheetEnvironment = OriginDestinationSheetEnvironment()

@StateObject private var locationServices = UserLocationServices.shared
@StateObject private var userLocationService = UserLocationServices.shared
@StateObject private var mapExtensionService = MapExtensionServices.shared

static let mockCoordinate = CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275)
static let mockSpan = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)

@State private var region = MKCoordinateRegion(center: mockCoordinate, span: mockSpan)
@State private var position: MapCameraPosition = .userLocation(fallback: .automatic)

public var body: some View {
ZStack {
Map(coordinateRegion: $region, showsUserLocation: true, userTrackingMode: .constant(.follow))
.edgesIgnoringSafeArea(.all)
MapReader { proxy in
Map(position: $position, interactionModes: .all) {
mapExtensionService
.generateMarkers()
}
.mapControls {
MapUserLocationButton()
MapPitchToggle()
}
.sheet(isPresented: $sheetEnvironment.isSheetOpened) {
OriginDestinationSheetView()
.environmentObject(sheetEnvironment)
}
.onTapGesture { tappedLocation in
guard let coordinate = proxy.convert(tappedLocation, from: .local) else { return }
mapExtensionService.appendMarker(coordinate: coordinate)
}
}

OriginDestinationView()
.environmentObject(sheetEnvironment)
VStack {
Spacer()
OriginDestinationView()
.environmentObject(sheetEnvironment)
}
}
.onAppear {
locationServices.checkIfLocationServicesIsEnabled()
userLocationService.checkIfLocationServicesIsEnabled()
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions OTPKitTests/Helpers/MockDataLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct MockDataResponse {

class MockTask: URLSessionDataTask {
override var progress: Progress {
return Progress()
Progress()
}

private var closure: (Data?, URLResponse?, Error?) -> Void
Expand Down Expand Up @@ -130,7 +130,7 @@ class MockDataLoader: NSObject, URLDataLoader {
// MARK: - URL Response

func buildURLResponse(URL: URL, statusCode: Int) -> HTTPURLResponse {
return HTTPURLResponse(
HTTPURLResponse(
url: URL,
statusCode: statusCode,
httpVersion: "2",
Expand Down
2 changes: 1 addition & 1 deletion OTPKitTests/Helpers/OTPTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class OTPTestCase: XCTestCase {
}

var userDefaultsSuiteName: String {
return String(describing: self)
String(describing: self)
}

// MARK: - Network and Data
Expand Down
2 changes: 1 addition & 1 deletion project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ settings:

options:
deploymentTarget:
iOS: "16.0"
iOS: "17.0"

targets:
OTPKitDemo:
Expand Down
2 changes: 1 addition & 1 deletion scripts/swiftformat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ if [[ "$(uname -m)" == arm64 ]]; then
fi

if which swiftformat > /dev/null; then
swiftformat .
swiftformat . --swiftversion 5.9
else
echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat"
fi

0 comments on commit 4f79722

Please sign in to comment.