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

Detail callout accessory view #46

Open
wants to merge 6 commits into
base: main
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
9 changes: 7 additions & 2 deletions Sources/Annotations/MKMapAnnotationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,23 @@
import MapKit
import SwiftUI

class MKMapAnnotationView<Content: View>: MKAnnotationView {
class MKMapAnnotationView<Content: View, DetailCalloutAccessory: View>: MKAnnotationView {

// MARK: Stored Properties

private var controller: NativeHostingController<Content>?

// MARK: Methods

func setup(for mapAnnotation: ViewMapAnnotation<Content>) {
func setup(for mapAnnotation: ViewMapAnnotation<Content, DetailCalloutAccessory>) {
annotation = mapAnnotation.annotation
clusteringIdentifier = mapAnnotation.clusteringIdentifier

if DetailCalloutAccessory.self != EmptyView.self {
canShowCallout = true
detailCalloutAccessoryView = NativeHostingController(rootView: mapAnnotation.detailCalloutAccessory).view
}

let controller = NativeHostingController(rootView: mapAnnotation.content)
addSubview(controller.view)
bounds.size = controller.preferredContentSize
Expand Down
21 changes: 18 additions & 3 deletions Sources/Annotations/MapMarker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import MapKit
import SwiftUI

@available(macOS 11, *)
public struct MapMarker {
public struct MapMarker<DetailCalloutAccessory: View> {

// MARK: Nested Types

Expand All @@ -34,22 +34,33 @@ public struct MapMarker {
private let coordinate: CLLocationCoordinate2D
private let tint: Color?
private let nativeTint: NativeColor?
private let detailCalloutAccessory: DetailCalloutAccessory
public let annotation: MKAnnotation

// MARK: Initialization

public init(coordinate: CLLocationCoordinate2D, tint: NativeColor? = nil) {
public init(
coordinate: CLLocationCoordinate2D,
tint: NativeColor? = nil,
@ViewBuilder detailCalloutAccessory: () -> DetailCalloutAccessory = { EmptyView() }
) {
self.coordinate = coordinate
self.tint = nil
self.nativeTint = tint
self.detailCalloutAccessory = detailCalloutAccessory()
self.annotation = Annotation(coordinate)
}

@available(iOS 14, tvOS 14, *)
public init(coordinate: CLLocationCoordinate2D, tint: Color?) {
public init(
coordinate: CLLocationCoordinate2D,
tint: Color?,
@ViewBuilder detailCalloutAccessory: () -> DetailCalloutAccessory = { EmptyView() }
) {
self.coordinate = coordinate
self.tint = tint
self.nativeTint = nil
self.detailCalloutAccessory = detailCalloutAccessory()
self.annotation = Annotation(coordinate)
}

Expand All @@ -69,6 +80,10 @@ extension MapMarker: MapAnnotation {
public func view(for mapView: MKMapView) -> MKAnnotationView? {
let view = mapView.dequeueReusableAnnotationView(withIdentifier: Self.reuseIdentifier, for: annotation)
view.annotation = annotation
if DetailCalloutAccessory.self != EmptyView.self {
view.canShowCallout = true
view.detailCalloutAccessoryView = NativeHostingController(rootView: detailCalloutAccessory).view
}
if let marker = view as? MKMarkerAnnotationView {
if #available(iOS 14, tvOS 14, *), let tint = tint {
marker.markerTintColor = .init(tint)
Expand Down
20 changes: 17 additions & 3 deletions Sources/Annotations/MapPin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extension MapPin: MapAnnotation {

#else

public struct MapPin {
public struct MapPin<DetailCalloutAccessory: View> {

// MARK: Nested Types

Expand All @@ -62,20 +62,30 @@ public struct MapPin {

private let coordinate: CLLocationCoordinate2D
private let tint: Color?
private let detailCalloutAccessory: DetailCalloutAccessory
public let annotation: MKAnnotation

// MARK: Initialization

public init(coordinate: CLLocationCoordinate2D) {
public init(
coordinate: CLLocationCoordinate2D,
@ViewBuilder detailCalloutAccessory: () -> DetailCalloutAccessory = { EmptyView() }
) {
self.coordinate = coordinate
self.tint = nil
self.detailCalloutAccessory = detailCalloutAccessory()
self.annotation = Annotation(coordinate)
}

@available(iOS 14, macOS 11, tvOS 14, *)
public init(coordinate: CLLocationCoordinate2D, tint: Color?) {
public init(
coordinate: CLLocationCoordinate2D,
tint: Color?,
@ViewBuilder detailCalloutAccessory: () -> DetailCalloutAccessory = { EmptyView() }
) {
self.coordinate = coordinate
self.tint = tint
self.detailCalloutAccessory = detailCalloutAccessory()
self.annotation = Annotation(coordinate)
}

Expand All @@ -94,6 +104,10 @@ extension MapPin: MapAnnotation {
public func view(for mapView: MKMapView) -> MKAnnotationView? {
let view = mapView.dequeueReusableAnnotationView(withIdentifier: Self.reuseIdentifier, for: annotation)
view.annotation = annotation
if DetailCalloutAccessory.self != EmptyView.self {
view.canShowCallout = true
view.detailCalloutAccessoryView = NativeHostingController(rootView: detailCalloutAccessory).view
}
if #available(iOS 14, macOS 11, tvOS 14, *), let tint = tint, let pin = view as? MKPinAnnotationView {
pin.pinTintColor = .init(tint)
}
Expand Down
17 changes: 11 additions & 6 deletions Sources/Annotations/ViewMapAnnotation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
import MapKit
import SwiftUI

public struct ViewMapAnnotation<Content: View>: MapAnnotation {
public struct ViewMapAnnotation<Content: View, DetailCalloutAccessory: View>: MapAnnotation {

// MARK: Nested Types

private class Annotation: NSObject, MKAnnotation {
class Annotation: NSObject, MKAnnotation {

// MARK: Stored Properties

Expand All @@ -35,14 +35,15 @@ public struct ViewMapAnnotation<Content: View>: MapAnnotation {
// MARK: Static Functions

public static func registerView(on mapView: MKMapView) {
mapView.register(MKMapAnnotationView<Content>.self, forAnnotationViewWithReuseIdentifier: reuseIdentifier)
mapView.register(MKMapAnnotationView<Content, DetailCalloutAccessory>.self, forAnnotationViewWithReuseIdentifier: reuseIdentifier)
}

// MARK: Stored Properties

public let annotation: MKAnnotation
let clusteringIdentifier: String?
let content: Content
let detailCalloutAccessory: DetailCalloutAccessory

// MARK: Initialization

Expand All @@ -51,19 +52,23 @@ public struct ViewMapAnnotation<Content: View>: MapAnnotation {
title: String? = nil,
subtitle: String? = nil,
clusteringIdentifier: String? = nil,
@ViewBuilder content: () -> Content
@ViewBuilder content: () -> Content,
@ViewBuilder detailCalloutAccessory: () -> DetailCalloutAccessory = { EmptyView() }
) {
self.annotation = Annotation(coordinate: coordinate, title: title, subtitle: subtitle)
self.detailCalloutAccessory = detailCalloutAccessory()
self.clusteringIdentifier = clusteringIdentifier
self.content = content()
}

public init(
annotation: MKAnnotation,
clusteringIdentifier: String? = nil,
@ViewBuilder content: () -> Content
@ViewBuilder content: () -> Content,
@ViewBuilder detailCalloutAccessory: () -> DetailCalloutAccessory = { EmptyView() }
) {
self.annotation = annotation
self.detailCalloutAccessory = detailCalloutAccessory()
self.clusteringIdentifier = clusteringIdentifier
self.content = content()
}
Expand All @@ -74,7 +79,7 @@ public struct ViewMapAnnotation<Content: View>: MapAnnotation {
let view = mapView.dequeueReusableAnnotationView(
withIdentifier: Self.reuseIdentifier,
for: annotation
) as? MKMapAnnotationView<Content>
) as? MKMapAnnotationView<Content, DetailCalloutAccessory>

view?.setup(for: self)
return view
Expand Down
17 changes: 8 additions & 9 deletions Sources/Map/Map.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extension Map {
interactionModes: MapInteractionModes = .all,
annotationItems: AnnotationItems,
@MapAnnotationBuilder annotationContent: @escaping (AnnotationItems.Element) -> MapAnnotation,
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping (MKClusterAnnotation, [AnnotationItems.Element]) -> MapAnnotation? = { _ in nil },
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping (MKClusterAnnotation, [AnnotationItems.Element]) -> MapAnnotation? = { _, _ in nil },
overlayItems: OverlayItems,
@MapOverlayBuilder overlayContent: @escaping (OverlayItems.Element) -> MapOverlay
) {
Expand Down Expand Up @@ -282,7 +282,6 @@ extension Map where AnnotationItems == [IdentifiableObject<MKAnnotation>] {
annotationItems: annotations.map(IdentifiableObject.init),
annotationContent: { annotationContent($0.object) },
clusterAnnotation: { annotation, _ in clusterAnnotation(annotation) },
clusterAnnotation: { annotation, _ in clusterAnnotation(annotation) },
overlayItems: overlayItems,
overlayContent: overlayContent
)
Expand Down Expand Up @@ -473,7 +472,7 @@ extension Map where OverlayItems == [IdentifiableObject<MKOverlay>] {
interactionModes: MapInteractionModes = .all,
annotationItems: AnnotationItems,
@MapAnnotationBuilder annotationContent: @escaping (AnnotationItems.Element) -> MapAnnotation,
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping ([AnnotationItems.Element]) -> MapAnnotation? = { _ in nil },
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping (MKClusterAnnotation, [AnnotationItems.Element]) -> MapAnnotation? = { _, _ in nil },
overlays: [MKOverlay] = [],
@MapOverlayBuilder overlayContent: @escaping (MKOverlay) -> MapOverlay = { overlay in
assertionFailure("Please provide an `overlayContent` closure for the values in `overlays`.")
Expand Down Expand Up @@ -504,7 +503,7 @@ extension Map where OverlayItems == [IdentifiableObject<MKOverlay>] {
interactionModes: MapInteractionModes = .all,
annotationItems: AnnotationItems,
@MapAnnotationBuilder annotationContent: @escaping (AnnotationItems.Element) -> MapAnnotation,
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping ([AnnotationItems.Element]) -> MapAnnotation? = { _ in nil },
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping (MKClusterAnnotation, [AnnotationItems.Element]) -> MapAnnotation? = { _, _ in nil },
overlays: [MKOverlay] = [],
@MapOverlayBuilder overlayContent: @escaping (MKOverlay) -> MapOverlay = { overlay in
assertionFailure("Please provide an `overlayContent` closure for the values in `overlays`.")
Expand Down Expand Up @@ -537,7 +536,7 @@ extension Map where OverlayItems == [IdentifiableObject<MKOverlay>] {
userTrackingMode: Binding<UserTrackingMode>?,
annotationItems: AnnotationItems,
@MapAnnotationBuilder annotationContent: @escaping (AnnotationItems.Element) -> MapAnnotation,
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping ([AnnotationItems.Element]) -> MapAnnotation? = { _ in nil },
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping (MKClusterAnnotation, [AnnotationItems.Element]) -> MapAnnotation? = { _, _ in nil },
overlays: [MKOverlay] = [],
@MapOverlayBuilder overlayContent: @escaping (MKOverlay) -> MapOverlay = { overlay in
assertionFailure("Please provide an `overlayContent` closure for the values in `overlays`.")
Expand Down Expand Up @@ -571,7 +570,7 @@ extension Map where OverlayItems == [IdentifiableObject<MKOverlay>] {
userTrackingMode: Binding<UserTrackingMode>?,
annotationItems: AnnotationItems,
@MapAnnotationBuilder annotationContent: @escaping (AnnotationItems.Element) -> MapAnnotation,
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping ([AnnotationItems.Element]) -> MapAnnotation? = { _ in nil },
@OptionalMapAnnotationBuilder clusterAnnotation: @escaping (MKClusterAnnotation, [AnnotationItems.Element]) -> MapAnnotation? = { _, _ in nil },
overlays: [MKOverlay] = [],
@MapOverlayBuilder overlayContent: @escaping (MKOverlay) -> MapOverlay = { overlay in
assertionFailure("Please provide an `overlayContent` closure for the values in `overlays`.")
Expand Down Expand Up @@ -708,7 +707,7 @@ extension Map where AnnotationItems == [IdentifiableObject<MKAnnotation>], Overl
interactionModes: interactionModes,
annotationItems: annotations.map(IdentifiableObject.init),
annotationContent: { annotationContent($0.object) },
clusterAnnotation: { clusterAnnotation($0.map(\.object)) },
clusterAnnotation: { annotation, _ in clusterAnnotation(annotation) },
overlayItems: overlays.map(IdentifiableObject.init),
overlayContent: { overlayContent($0.object) }
)
Expand Down Expand Up @@ -742,7 +741,7 @@ extension Map where AnnotationItems == [IdentifiableObject<MKAnnotation>], Overl
interactionModes: interactionModes,
annotationItems: annotations.map(IdentifiableObject.init),
annotationContent: { annotationContent($0.object) },
clusterAnnotation: { clusterAnnotation($0.map(\.object)) },
clusterAnnotation: { annotation, _ in clusterAnnotation(annotation) },
overlayItems: overlays.map(IdentifiableObject.init),
overlayContent: { overlayContent($0.object) }
)
Expand Down Expand Up @@ -779,7 +778,7 @@ extension Map where AnnotationItems == [IdentifiableObject<MKAnnotation>], Overl
userTrackingMode: userTrackingMode,
annotationItems: annotations.map(IdentifiableObject.init),
annotationContent: { annotationContent($0.object) },
clusterAnnotation: { clusterAnnotation($0.map(\.object)) },
clusterAnnotation: { annotation, _ in clusterAnnotation(annotation) },
overlayItems: overlays.map(IdentifiableObject.init),
overlayContent: { overlayContent($0.object) }
)
Expand Down