Swift Mkmapview Drop a Pin Annotation to Current Location

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,

Sample Image



Related Topics



Leave a reply



Submit