Swift MKMapView Drop a Pin Annotation to Current Location
If you want to add pin to user location you can do that in didUpdateLocations
delegate method like this
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
mapView.removeAnnotation(newPin)
let location = locations.last! as CLLocation
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
//set region on the map
map.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
map.addAnnotation(newPin)
}
Create a global variable for your pin
let newPin = MKPointAnnotation()
So whenever user will move to a new location the previous pin will be removed and a new pin will be added to updated location.
Drop pin and get adress from where the user tap on map
If you want to getAdress where the user taps that is a tricky part,
By following this link
OR
You can do with dragging by pin:
Step 1: Drop pin on current location. By following this
Step 2: By dragging pin you can get the current pin position address. By following this:
MapKit- How to add location constraints for dropping a pin?
You can use distance(from: )
method.
See: https://developer.apple.com/documentation/corelocation/cllocation/1423689-distance
@IBAction func addPin(sender: UILongPressGestureRecognizer) {
//locating where to drop the pin
let location = sender.locationInView(self.mapView)
let locCoord = self.mapView.convertPoint(location, toCoordinateFromView:
self.mapView)
// Get distance between pressed location and user location
let pressedLocation = CLLocation(latitude: locCoord.latitude, longitude: locCoord.longitude)
// let distanceInMeters = self.mapView.userLocation.location?.distance(from: pressedLocation) // >= Swift 3
let distanceInMeters = self.mapView.userLocation.location?.distanceFromLocation(pressedLocation) // < Swift 3
// You get here distance in meter so 10 miles = 16090 meter
if let distanceInMeters = distanceInMeters, distanceInMeters > 16090 {
// out of 10 mile (don't drop pin)
return
}
let annotation = MKPointAnnotation()
annotation.coordinate = locCoord
annotation.title = "Test"
annotation.subtitle = "subtext"
//remove map point (use later)
self.mapView.removeAnnotations(mapView.annotations)
self.mapView.addAnnotation(annotation)
}
However, there are couple of things that you need to put in place first.
- You need to ask the user for permission to use their location. That includes calling CLLocationManager's requestWhenInUseAuthorization and checking for the asynchronous result.
- Adding NSLocationWhenInUseUsageDescription entry to your info (described in the link above) to tell the user what you want to do with the information
How do I get a dropped pin inside a MapView to save coordinates and present them as a String using SwiftUI?
Hello I managed to get the solution.
Will add code only which is changed
// Made this a ObservableObject
class Meuf: Identifiable, Codable, ObservableObject {
var id = UUID()
var img = ""
var title = ""
var rating = 3.0
var seen = false
var seenDate = ""
var locations = [CodableMKPointAnnotation]() // We need this to keep the track of locations
}
FormView
struct FormView: View {
@State private var selectedTitle = ""
@ObservedObject var meufObject = Meuf() // This is new will help to keep track of the added locations
@State private var meufs = [Meuf]()
@State private var show = false
@State private var singleIsPresented = false
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var meufStorage : MeufStorage
@State private var showMap = false
var body: some View {
NavigationView{
Form {
List {
// This will list the added locations now
ForEach(self.meufObject.locations, id: \.self) { location in
LocationView(location: location)
}
}
//MARK: LOCATION
Section{
HStack {
Button(action: { self.showMap = true }) {
Image(systemName: "mappin.and.ellipse")
}
.sheet(isPresented: $showMap) {
LocationMap(meufObject: self.meufObject, showModal: self.$showMap)
}
Text("Pin your location")
.font(.subheadline)
}
}
// MARK: [ SAVE ENTRY ]
Section {
Button(action: {
// Handle save action
}) {
HStack{
Spacer()
Text("Save")
Spacer()
}
}
}
}
}
}
// Rest of your code stays same .......
}
// Added this new view to render the location view
struct LocationView: View {
var location : CodableMKPointAnnotation
var body: some View {
Text(location.title ?? "title" )
}
}
LocationMap
struct LocationMap: View {
@ObservedObject var meufObject: Meuf // This is new will help to keep track of the added locations
@State private var centerCoordinate = CLLocationCoordinate2D()
@State private var locations = [CodableMKPointAnnotation]()
@State private var selectedPlace: MKPointAnnotation?
@State private var showingPlaceDetails = false
@State private var showingEditScreen = false
@Environment(\.presentationMode) var presentationMode
@Binding var showModal: Bool
var body: some View {
ZStack{
MapView(centerCoordinate: $centerCoordinate, annotations: locations, selectedPlace: $selectedPlace, showingPlaceDetails: $showingPlaceDetails)
.edgesIgnoringSafeArea(.all)
Circle()
.fill(Color.blue)
.opacity(0.3)
.frame(width: 32, height: 32)
VStack {
Spacer()
HStack{
Spacer()
Button(action:{
let newLocation = CodableMKPointAnnotation()
newLocation.title = ""
newLocation.coordinate = self.centerCoordinate
self.locations.append(newLocation)
self.meufObject.locations = self.locations // By doing this we will be able to pass it to main screen
self.selectedPlace = newLocation
self.showingEditScreen = true
}){
Image(systemName: "plus")
}
.padding()
.background(Color.black.opacity(0.7))
.foregroundColor(Color.white)
.clipShape(Circle())
.shadow(radius: 0.7)
.padding([.trailing , .bottom])
// Rest stays same as your implementation
}
}
.padding()
}
}
// Rest stays same as your implementation
}
Adding a pin annotation to a map view on a long press in swift
1) Instantiate a UILongPressGestureRecognizer
and add it to the MKMapView
.
2) When the selector gets called after the user has a long press, call the addAnnotation method in MKMapView
with the appropriate title and coordinate.
3) Then make sure you conform to the MKMapViewDelegate
and implement viewForAnnotation:
which will be called right after you add the annotation and return a MKPinAnnotationView
MapKit functionality on a UIImage, dropping pins/Annotation
The same can be achieved by following the same procedure with a few tweaks here and there. I've made a sample ViewController
that demonstrates how you can add pointers (UIViews
in this case) into a UIImageView
.
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView! // Image view
lazy var longPress = UILongPressGestureRecognizer(target: self, action: #selector(didLongPressScreen)) // long press gesture
// MARK: LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setup()
}
// MARK: Functions
private func setup() {
imageView.image = UIImage(named: "photo")
imageView.addGestureRecognizer(longPress) // Adding gesture recognizer
imageView.isUserInteractionEnabled = true // ImageViews are not user interactive by default
}
// UILongPressGestureRecognizer Action
@objc func didLongPressScreen(_ sender: UILongPressGestureRecognizer) {
let location = sender.location(in: self.view) //Getting location
DispatchQueue.main.async {
let pointer = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
pointer.backgroundColor = .red
pointer.center = location // Setting the center of the view to the x,y coordinates of the long press
self.view.addSubview(pointer) // Adding the UIView to the view
}
}
}
The most important part of this is to enable the user interaction for the UIImageView
as its. isUserInteractionEnabled
is set to false
by default. The output of the above can be seen below,
Related Topics
My Data Changes in Uitableviewcell When I Scroll Down and Get Back
Display All Available Wifi Connections with Swift in Os X
Why Can't I Change Variables in a Protocol Extension Where Self Is a Class
Select All Text in Textfield Upon Click Swiftui
Break on Any Occurrence of "Fatal Error: Unexpectedly Found Nil While Unwrapping an Optional Value"
Retrieving Keys from Geofire Within Radius in Swift
Swift Error: Guard Body Must Not Fall Through
How to Create a Static Class in Swift
Swift Extension for Selected Class Instance
Error: Bool Is Not Convertible to Void:
How to List Swift Types That Conform to Protocol Using Reflection
Open File Dialog Crashes in Swift
How to Detect Switch Between MACos Default & Dark Mode Using Swift 3
Swift 4 Attributedstring Get Typing Attributes
What Are the Advantages/Use Cases of Optional Patterns Introduced in Swift 2
Can't Parse JSON Array with JSONdecoder in Swift 4
Can't Pass Date to Nspredicate(Format: ...) Without "As Cvararg"
Why Does an @Objc Enum Have a Different Description Than a Pure Swift Enum