I've been trying to create a mapmarker on my screen via mapkit for 1 week. These mapmarkers come from the api I have as latitude and longitude. However, I learned swift 1 month ago and I'm having a hard time. Is there someone to help me? Code and screenshot attached.
Obviously what I want is to know where to write the codes and to know which codes to use. (My interface is swift, there is usually a storyboard interface on the internet)
import SwiftUI
import MapKit
struct depremHaritasi: View {
#State var quakes: [EarthQuake] = []
#State var coordinateRegion = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 38.9520281, longitude: 35.6980142),
span: MKCoordinateSpan(latitudeDelta: 30, longitudeDelta: 10))
var body: some View {
Map(coordinateRegion: $coordinateRegion)
.edgesIgnoringSafeArea(.all)
.onAppear {
Api().getEarthQuake { (quakes) in
self.quakes = quakes
}
}
}
}
struct depremHaritasi_Previews: PreviewProvider {
static var previews: some View {
depremHaritasi()
}
}
Earthquake Map Screenshot
Related
I'm new to swiftUI and I made this view where you see a maps with different pins on it. I wanted it so when I click the pin it shows a little box above it with the info about the place (name, address)
I found other threads about it but I couldn't really find what I needed.
Anybody who could help me?
import SwiftUI
import MapKit
struct MyAnnotationItem: Identifiable {
var coordinate: CLLocationCoordinate2D
let id = UUID()
}
struct MapView: View {
#State var coordinateRegion: MKCoordinateRegion = {
var newRegion = MKCoordinateRegion()
newRegion.center.latitude = 50.80580148204638
newRegion.center.longitude = 3.2842106137743308
newRegion.span.latitudeDelta = 0.2
newRegion.span.longitudeDelta = 0.2
return newRegion
}()
var annotationItems: [MyAnnotationItem] = [
//castel motors
MyAnnotationItem(coordinate: CLLocationCoordinate2D(latitude: 50.690042667142485, longitude: 3.1734146440963777)),
//leon saggaert
MyAnnotationItem(coordinate: CLLocationCoordinate2D(latitude: 50.94343953661561, longitude: 3.2940420541585396)),
//R4 motos
MyAnnotationItem(coordinate: CLLocationCoordinate2D(latitude: 51.09466176530236, longitude: 3.7763867274168774)),
//garden tools
MyAnnotationItem(coordinate: CLLocationCoordinate2D(latitude: 50.78567261592435, longitude: 3.2141870141679365)),
//desmet roland
MyAnnotationItem(coordinate: CLLocationCoordinate2D(latitude: 50.87668047058957, longitude: 3.442740743366995)),
//r trac
MyAnnotationItem(coordinate: CLLocationCoordinate2D(latitude: 50.853492889583116, longitude: 3.7401561581010645))
]
var body: some View {
VStack {
Map(coordinateRegion: $coordinateRegion,
annotationItems: annotationItems) {item in
MapMarker(coordinate: item.coordinate)
}
}
.ignoresSafeArea()
}
}
struct Previews_SwiftUIMap_Previews: PreviewProvider {
static var previews: some View {
MapView()
}
}
I made the view with the pins, now I only need them to be clickable
My app now
I pulled the data from the mapmarker, when I print, I see all of them, but I cannot get them from the example ( quake.latitude ). Error. Even if it was a list, I had taken it by typing "(quakes) { quake in" in parentheses, but now I don't know how to do it through mapview.
struct MapAnnotationsView: View {
#State var quakes: [EarthQuake] = []
#State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 38.9520281, longitude: 35.6980142), span: MKCoordinateSpan(latitudeDelta: 30, longitudeDelta: 10))
let placeArray: [Place] = [Place(title: {quake.latitude}, coordinate: CLLocationCoordinate2D(latitude: 37.8008, longitude: 27.2465))]
var body: some View {
Map(coordinateRegion: $region, annotationItems: placeArray) { annotation in
// This makes a generic annotation that takes a View
MapAnnotation(coordinate: annotation.coordinate) {
// This is your custom view
AnnotationView(placeName: annotation.title)
}
} .onAppear {
Api().getEarthQuake { (quakes) in
self.quakes = quakes
}
}
}
}
Error code screenshot
Try this:
struct MapAnnotationsView: View {
#State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 38.9520281, longitude: 35.6980142), span: MKCoordinateSpan(latitudeDelta: 30, longitudeDelta: 10))
#State private var placeArray: [Place] = []
var body: some View {
Map(coordinateRegion: $region, annotationItems: placeArray) { annotation in
// This makes a generic annotation that takes a View
MapAnnotation(coordinate: annotation.coordinate) {
// This is your custom view
AnnotationView(placeName: annotation.title)
}
} .onAppear {
Api().getEarthQuake { (quakes) in
let tempArray = quakes.map{ quake in
Place(title: "\(quake.latitude)", coordinate: CLLocationCoordinate2D(latitude: 37.8008, longitude: 27.2465))
}
self.placeArray = tempArray
}
}
}
}
As this is not a reproducible example there might be some typos involved here which you would have to address yourself.
Explenation:
Your property placeArray cannot depend on another property. To get an array of places to provide to your map you need to create these after you loaded the earthquakes from your API and assign them. Using a #State var ensures your View gets updated.
I've done the application I'm making to swift with react native before, but I can't reach the result I want when creating a marker on a mapkit.
Instantly updated earthquakes are coming on Api, I want to show 100 of these earthquakes as markers. I did the display operation in the API, but the adjacent order created a diagonal marker.
I have a few questions for this project.
my coding with React native
The screen I made on Android, the screen I wanted in swift
screen in Swift
this is my code that i wrote in swift, i need some help i couldn't find any example about this issue. I hope you understand my problem.
import SwiftUI
import CoreLocation
import MapKit
struct MapAnnotationsView: View {
#State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 38.9520281, longitude: 35.6980142), span: MKCoordinateSpan(latitudeDelta: 30, longitudeDelta: 10))
#State private var placeArray: [Place] = []
var body: some View {
Map(coordinateRegion: $region, annotationItems: placeArray) { annotation in
// This makes a generic annotation that takes a View
MapAnnotation(coordinate: annotation.coordinate) {
// This is your custom view
AnnotationView(placeName: annotation.title)
}
} .onAppear {
Api().getEarthQuake { (quakes) in
let tempArray = quakes.map{ quake in
Place(title: "\(quake.yer)", coordinate: CLLocationCoordinate2D(latitude: Double.init(quake.enlem)!, longitude: Double.init(quake.enlem)!))
}
self.placeArray = tempArray
}
}
}
}
struct AnnotationView: View {
let placeName: String
#State private var showPlaceName = false
var body: some View {
VStack(spacing: 0) {
Text(placeName)
.font(.callout)
.padding(15)
.background(Color.white)
.cornerRadius(10)
// Prevents truncation of the Text
.fixedSize(horizontal: true, vertical: false)
// Displays and hides the place name
.opacity(showPlaceName ? 1 : 0)
// You can use whatever you want here. This is a custom annotation marker
// made to look like a standard annotation marker.
Image(systemName: "mappin.circle.fill")
.font(.title)
.foregroundColor(.red)
Image(systemName: "arrowtriangle.down.fill")
.font(.caption)
.foregroundColor(.red)
.offset(x: 0, y: -5)
}
.onTapGesture {
withAnimation(.easeInOut) {
showPlaceName.toggle()
}
}
}
}
struct Place: Identifiable {
let id = UUID()
var title: String
var coordinate: CLLocationCoordinate2D
}
I am setting up a MapView with custom coordinates. Here is my code thus far
var coordModel: AirportModel?
struct MapView: View {
#Binding private var lat: Double
#Binding private var lon: Double
private let initialLatitudinalMetres: Double = coordModel?.airportLat ?? 0
private let initialLongitudinalMetres: Double = coordModel?.airportLong ?? 0
#State private var span: MKCoordinateSpan?
init(lat: Binding<Double>, lon: Binding<Double>) {
_lat = lat
_lon = lon
}
private var region: Binding<MKCoordinateRegion> {
Binding {
let centre = CLLocationCoordinate2D(latitude: lat, longitude: lon)
if let span = span {
return MKCoordinateRegion(center: centre, span: span)
} else {
return MKCoordinateRegion(center: centre, latitudinalMeters: initialLatitudinalMetres, longitudinalMeters: initialLongitudinalMetres)
}
} set: { region in
lat = region.center.latitude
lon = region.center.longitude
span = region.span
}
}
var body: some View {
Map(coordinateRegion: region)
}
}
In the AirportModel, there is a piece of data decoded in Double form called "latitude" and "longitude." I am simply trying to pass these data into the view after they are decoded. Here is my view body:
var body: some View {
ScrollView{
MapView(lat: <#Binding<Double>#>, lon: <#Binding<Double>#>)
.frame(height: 250)
.edgesIgnoringSafeArea(/*#START_MENU_TOKEN#*/.all/*#END_MENU_TOKEN#*/)
}
I have tried putting coordModel?.latitude and coordModel?.longitude in for lat and lon, as well as setting variables above the call. I'm not quite sure where to go now.
Note: I am decoding a bunch of JSON data and every user query results in a different lat/lon pull (over 10000 potential responses). Thanks again!
Use a model that is an ObservableObject:
import Combine
import MapKit
class MapModel: ObservableObject {
var region: MKCoordinateRegion = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 48.687330584, longitude: 9.219832454),
latitudinalMeters: 1000000,
longitudinalMeters: 1000000
) {
willSet {
self.objectWillChange.send()
}
}
// MARK: - test code change center evey 10 seconds
init() {
self.timer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in
self.testIndex += 1
self.testIndex %= self.testCoordinates.count
let newCenter = self.testCoordinates[self.testIndex]
let oldSpan = self.region.span
DispatchQueue.main.async {
self.region = MKCoordinateRegion(center: newCenter, span: oldSpan)
}
}
}
let testCoordinates = [
CLLocationCoordinate2D(latitude: 48.687330584, longitude: 9.219832454), // STR
CLLocationCoordinate2D(latitude: 41.297445, longitude: 2.0832941), // BCN
]
var testIndex: Int = 0
var timer: Timer? = nil
}
then create a View that observes your model
import SwiftUI
import MapKit
struct ContentView: View {
#ObservedObject private var mapModel = MapModel()
var body: some View {
Map(coordinateRegion: $mapModel.region)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
For test reasons I used a timer that simulates updated data from a server.
If you need Annotations, add them to the model and don't forget self.objectWillChange.send() if you change them.
How can I add a simple pin on my map with Xcode 11 GM / SwiftUI.
My code is as follows (here it shows me the map centered with the coordinates) but I want to show there only one pin of other coordinates.
import SwiftUI
import MapKit
struct ContentView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
let coordinate = CLLocationCoordinate2D(
latitude: 34.011_286, longitude: -116.166_868)
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I would appreciate any suggestions, thanks.
Update your code:
struct ContentView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
// 1
view.mapType = MKMapType.standard // (satellite)
// 2
let mylocation = CLLocationCoordinate2D(latitude: -6.863190,longitude: -79.818250)
// 3
let coordinate = CLLocationCoordinate2D(
latitude: -6.864138, longitude: -79.819634)
let span = MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
// 4
let annotation = MKPointAnnotation()
annotation.coordinate = mylocation
annotation.title = "My Location"
annotation.subtitle = "Visit us soon"
view.addAnnotation(annotation)
}
}
Found this post looking for how to add a simple pin/marker to XCode's MapKit and SwiftUI tutorials. Sharing a workable answer for using the new Map SwiftUI View rather than the more complex MKMapView in OP's question.
import SwiftUI
import MapKit
struct Marker: Identifiable {
let id = UUID()
var location: MapMarker
}
struct MapView: View {
var coordinate: CLLocationCoordinate2D
#State private var region = MKCoordinateRegion()
#State var markers = [Marker(location: MapMarker(coordinate: CLLocationCoordinate2D(latitude: -25.342863, longitude: 131.036974), tint: .blue))]
var body: some View {
Map(coordinateRegion: $region, annotationItems: markers) { marker in
marker.location }
.onAppear {
setRegion(coordinate)
}
}
private func setRegion(_ coordinate: CLLocationCoordinate2D) {
region = MKCoordinateRegion(
center: coordinate,
span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
)
markers = [Marker(location: MapMarker(coordinate: coordinate, tint: .blue))]
}
}
struct MapView_Previews: PreviewProvider {
static var previews: some View {
MapView(coordinate: CLLocationCoordinate2D(latitude: -25.342863, longitude: 131.036974))
}
}