arraysswiftuireferencemapkitgoogle-maps-markers

SwiftUI Mapkit: How to reference values from an array for markers?


I am a beginner, and I have a programming-related question:

I have an array mit values for markers, which I want to present an a map. The market is shown, so no problem.

But: I don't arrive in using my values for the marker, as for example the tint-color. I know how to get the value "coordinates" (by using n.coordinate), but the name (which is a String) or the tint (which is a Color) does not work, I simply don't know how to reference it (n.name doesn't work).

import SwiftUI
import MapKit

struct MyLocationsArray: Identifiable {       // MyLocationArray: Alle Locations sind in diesem Array erfasst
    let id = UUID()
    let number: Int                          // lfd. Nummer der eigenen Locations: 1, 2,3,4, ... 
    let category: Int                        // Kategorie-Nr.: Historisches, Strände, etc.
    let name: String                         // Name der Location: "A-name"
    let label: String                        // abgekürzter Name unter dem Marker: "A-Label"
    let systemimage: String                  // Systemsymbol im Marker: "bird"
    let tint: Color                          // Farbe des Markers: .yellow, .green, .blue
    let coordinates: CLLocationCoordinate2D   // Koordinaten der Location
    let freeInt: Int                        // noch nicht belegt (Int) (default: 0)
    let freeString: String                   // noch nicht belegt (String) (default: "")
}

struct ContentView: View {
    
    let marker = [
        MyLocationsArray(number: 1, category: 1, name: "A-Name", label: "A-Label", systemimage: "bird", tint: .orange, coordinates: CLLocationCoordinate2D(latitude: 42.2926854029081, longitude: -71.0679634411345), freeInt: 0, freeString: ""),
              
        MyLocationsArray(number: 1, category: 1, name: "B-Name", label: "B-Label", systemimage: "bird", tint: .red, coordinates: CLLocationCoordinate2D(latitude: 42.2926854029081, longitude: -71.0679634411345), freeInt: 0, freeString: "")
    ]
    
    
    var body: some View {
        Text("Hello, World!")
        
        Map {
            ForEach(marker) { n in
                Marker("", coordinate: n.coordinates)     // ""** should be "label"**
                    .tint(.yellow)                        // **".yellow" should be individual **(see "let marker ...")
            } // ForEach
        }
    }
}

#Preview {
    ContentView()
})

I tried to find help by reading all about arrays at stack overflow an google, but for a beginner I didn't find anything.


Solution

  • Note: You had an extra ) at the end of the code which gave an error.

    If you know how to get the coordinates for a marker, then you know how to get any other property of the marker. To keep things clearer, it's best to use descriptive naming for variables, including the appropriate use of singular and plural.

    For example, in your code:

    ForEach(markers) { marker in 
    

    ... which makes everything much clearer for all:

    ForEach(markers) { marker in 
        Marker(marker.name, systemImage: marker.icon, coordinate: marker.coordinates)    
            .tint(marker.tint) 
    }
    

    Also:

    The full code below includes all these changes:

    import SwiftUI
    import MapKit
    
    struct MyLocationsArray: Identifiable {       // MyLocationArray: Alle Locations sind in diesem Array erfasst
        let id = UUID()
        let number: Int                          // lfd. Nummer der eigenen Locations: 1, 2,3,4, ... 
        let category: Int                        // Kategorie-Nr.: Historisches, Strände, etc.
        let name: String                         // Name der Location: "A-name"
        let label: String                        // abgekürzter Name unter dem Marker: "A-Label"
        let icon: String                  // Systemsymbol im Marker: "bird"
        let tint: Color                          // Farbe des Markers: .yellow, .green, .blue
        let coordinates: CLLocationCoordinate2D   // Koordinaten der Location
        let freeInt: Int                        // noch nicht belegt (Int) (default: 0)
        let freeString: String                   // noch nicht belegt (String) (default: "")
    }
    
    struct MyLocationsContentView: View {
        
        let markers = [ // <- for convenience, use plural for an array of objects
            MyLocationsArray(number: 1, category: 1, name: "A-Name", label: "A-Label", icon: "bird", tint: .orange, coordinates: CLLocationCoordinate2D(latitude: 42.2926854029081, longitude: -71.0679634411345), freeInt: 0, freeString: ""),
                  
            MyLocationsArray(number: 1, category: 1, name: "B-Name", label: "B-Label", icon: "tortoise", tint: .red, coordinates: CLLocationCoordinate2D(latitude: 42.2936854029081, longitude: -71.0679634411345), freeInt: 0, freeString: "") // <- your two markers had the same coordinates - changed the second one to be in a slightly different location so both can be visible
        ]
        
        
        var body: some View {
            Text("MapKit Mastery") // <- for amusement, use a funny title
            
            Map {
                ForEach(markers) { marker in // <- for convenience, use singular to reference a single object in the array
                    Marker(marker.name, systemImage: marker.icon, coordinate: marker.coordinates)     // <- can also be marker.label
                        .tint(marker.tint)                        // <- use the .tint property of the marker for the .tint modifier parameter
                } // ForEach
            }
        }
    }
    
    #Preview {
        MyLocationsContentView()
    }
    

    Finally, I see you have a category property for your marker object. If later you will want to show markers based on category or based on a selected category, maybe this answer will be helpful.

    enter image description here