How to remove Annotation from Map in Swift 2 [MapKit] - ios

I can add Annotation on MapView using "first" button, but I would like to add a new option which enables the removing of the annotation using the "second" button. I have no problem with adding annotation, but I cannot remove it from the map view. Can somebody help me in it?
Here is my code:
class ViewController: UIViewController {
#IBOutlet weak var mapViewOutlet: MKMapView!
var lm = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.lm.requestAlwaysAuthorization()
mapViewOutlet.showsUserLocation = true
mapViewOutlet.userTrackingMode = MKUserTrackingMode.Follow
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// HERE IS FUNCTION ADDANNOTATION
#IBAction func tagMyCar(sender: UIButton) {
let coordinate = lm.location?.coordinate
let CarCoordinates = CarAdnotaion(coordinate: coordinate!)
mapViewOutlet.addAnnotation(CarCoordinates)
let region = CLCircularRegion(center: coordinate!, radius: 5, identifier: "My Car")
region.notifyOnEntry = true
region.notifyOnExit = true
lm.startMonitoringForRegion(region)
}
// HERE IS FUNCTION REMOVEANNOTATION
#IBAction func removeAnnotationfromMap(sender: AnyObject) {
let region = CLCircularRegion(center: (lm.location?.coordinate)!, radius: 5, identifier: "Mój samochód")
self.mapViewOutlet.removeAnnotation(CarAdnotaion(coordinate: (lm.location?.coordinate)!))
lm.stopMonitoringForRegion(region)
}
}

I think the problem is here:
self.mapViewOutlet.removeAnnotation(CarAdnotaion(coordinate: (lm.location?.coordinate)!))
You are removing annotation that you just created in this very statemen. Instead, move let CarCoordinates up (and give it more sensible name and lowercase letter in the beginning). Then call removeAnnotation on that object.

I have a solution of my problem. It works!
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController {
#IBOutlet weak var mapViewOutlet: MKMapView!
let lm = CLLocationManager()
var carAnnotation: CarAnnotationOnMap?
var region: CLCircularRegion?
override func viewDidLoad() {
super.viewDidLoad()
self.lm.requestAlwaysAuthorization()
mapViewOutlet.userTrackingMode = MKUserTrackingMode.Follow
mapViewOutlet.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// ADD ANNOTATION ON MAP
#IBAction func tagMyCar(sender: UIButton) {
let coordinates = lm.location?.coordinate
carAnnotation = CarAnnotationOnMap(coordinates: coordinates!)
region = CLCircularRegion(center: coordinates!, radius: 5, identifier: "My Zone")
region!.notifyOnEntry = true
region!.notifyOnExit = true
self.lm.startMonitoringForRegion(region!)
mapViewOutlet.addAnnotation(carAnnotation!)
}
// REMOVE ANNOTATION FROM MAP
#IBAction func removePinFromMyCar(sender: AnyObject) {
self.lm.stopMonitoringForRegion(region!)
mapViewOutlet.removeAnnotation(carAnnotation!)
}
}

Related

stopUpdateLocation() doesn´t work swift

when I perform my segue, the location is still updated in the next VC. I tried to put the startUpdatingLocation() into an other function than the super view, but nothing changed. Do you have any ideas what i can do? Grüße aus Mannheim
import UIKit
import MapKit
import CoreLocation
class uploadPrepare: UIViewController, UITextViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var weiterButton: UIButton!
let locationPrepare = CLLocationManager()
var regionPrepare: MKCoordinateRegion!
override func viewDidLoad() {
super.viewDidLoad()
locationPrepare.delegate = self
locationPrepare.desiredAccuracy = kCLLocationAccuracyBest
locationPrepare.requestWhenInUseAuthorization()
locationPrepare.startUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func weiterButtonTapped(_ sender: UIButton){
self.locationPrepare.stopUpdatingLocation()
self.performSegue(withIdentifier: "goToMapCheck", sender: self)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locationPrepare = locations[0]
let myLocationPrepare:CLLocationCoordinate2D = CLLocationCoordinate2DMake(locationPrepare.coordinate.latitude,locationPrepare.coordinate.longitude)
let span: MKCoordinateSpan = MKCoordinateSpanMake(0.0005,0.0005)
regionPrepare = MKCoordinateRegionMake(myLocationPrepare,span)
print("\(locationPrepare.coordinate.latitude)")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let uploadInterfaceGoing = segue.destination as! mapCheck
uploadInterfaceGoing.regionReceived = regionPrepare
}
}

prepare for segue not being called with tabbarcontroller

Im using Xcode 8 and swift 3
I created a new project selecting new "Tabbed Application" when i created it. It provided two UIViewControllers embedded in one tab bar controller. I'm trying to pass two variables between the view controllers.
The problem is that the prepare for segue function is never called. I added a print statement in it that never prints. I added the prepare function in both view controllers and can tab back and forth with no prints.
Some code:
import UIKit
import MapKit
import CoreLocation
class FirstViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
#IBOutlet weak var mapView: MKMapView!
var locationManager:CLLocationManager?
var currentLocation:CLLocation?
var destPin: MapPin?
var isTracking: Bool? = false
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.startUpdatingLocation()
locationManager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager?.requestAlwaysAuthorization()
updateTracking()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
self.currentLocation = locations[0]
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getMapView()-> MKMapView{
return mapView
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
if(self.isTracking!){
print("Istracking bool is true")
}
else{
print("Istracking bool is false")
}
updateTracking()
locationManager?.stopUpdatingLocation()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("Preparing")
let barViewControllers = segue.destination as! UITabBarController
let destinationViewController = barViewControllers.viewControllers![1] as! FirstViewController
destinationViewController.destPin = self.destPin
destinationViewController.isTracking = self.isTracking
}
}
The contents of the prepare function may very well be wrong as well but without the function even being called it hardly matters. The other view controller is also embedded in the tab bar controller and also has a prepare function that does not execute.
If you'd like, its in this github repo
It is easy to do:
The result:
For example, there are FirstViewController and SecondViewController embeded in tabViewController:
In your firstViewController.swift:
import UIKit
class FirstViewController: UIViewController {
var vc1_variable:String = "first vc's variable."
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In your secondViewController.swift:
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let first_vc:FirstViewController = self.tabBarController?.viewControllers![0] as! FirstViewController
print("\(first_vc.vc1_variable)")
}
}

swift locationManager clear region cache

i have an App that does actions on didEnterRegion and didExitRegion of CLBeaconRegions. Those are both on my viewcontroller class. Now the user should be able to set the UUID by himself. Therefor I made a second view controller (setibeaconVC) to change the string of the UUID.
It does work however the regions increase overtime the user changes the UUID in the App. So the Actions are called first one time after changing the UUID once the actions are called two times and so on.
Is there any command to clear the cache of those regions before I change the UUID?
Here´s part of my code.
ViewController:
var ibeaconuuid:String! = "B9407F30-F5F8-466E-AFF9-25556B57FE6D"
let locationManager = CLLocationManager()
var beaconUUID:NSUUID!
var region:CLBeaconRegion!
override func viewDidLoad() {
super.viewDidLoad()
beaconUUID = NSUUID(UUIDString: ibeaconuuid)
region = CLBeaconRegion(proximityUUID: beaconUUID, identifier: "Beacon")
locationManager.delegate = self
locationManager.pausesLocationUpdatesAutomatically = false
region.notifyOnEntry = true
region.notifyOnExit = true
region.notifyEntryStateOnDisplay = false
if (CLLocationManager.authorizationStatus() != CLAuthorizationStatus.AuthorizedAlways) {
locationManager.requestAlwaysAuthorization()
}
if (CLLocationManager .isMonitoringAvailableForClass(CLBeaconRegion))
{
print("OK")
}
else {
print("Problem")
}
locationManager.startMonitoringForRegion(region)
locationManager.startRangingBeaconsInRegion(region)
locationManager.startUpdatingLocation()
}
And here the setiBeaconVC:
class setibeaconVC: UIViewController {
#IBOutlet weak var ibeaconuuidtext: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestViewController: ViewController = segue.destinationViewController as! ViewController
DestViewController.ibeaconuuid = ibeaconuuidtext.text!
}
}
Many Thanks
Stephan
Before re-creating the CLBeaconRegion in your view controller call locationManager.stopMonitoringForRegion(region).
You will need to check this contains a region before calling as on first run it won't. Easiest way to do this is to change region to an optional rather than forced unwrapped optional. Then check like this:
var region:CLBeaconRegion? // Update to this.
if let r = region {
locationManager.stopMonitoringForRegion(r)
}

this class is not key value coding-compliant for the key EventCreate

I'm new to Swift and iOS development. I'm trying to load a secondary view controller as an overlay over a mapView, and when I try to do it I run into the error listed in the title. I'm stumped.
My code is as follows:
// mainMapViewController.swift
import UIKit
import MapKit
import CoreLocation
var events = [Event]()
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UIGestureRecognizerDelegate {
#IBOutlet weak var mapView: MKMapView!
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let locationManager = CLLocationManager()
#IBAction func addEvent(mylongpress: UIGestureRecognizer) {
if mylongpress.state == UIGestureRecognizerState.Began {
let touchpoint = mylongpress.locationInView(mapView)
let newcoord = mapView.convertPoint(touchpoint, toCoordinateFromView: mapView)
let pin = MKPointAnnotation()
pin.coordinate = newcoord
let eventcreatevc = mainStoryBoard.instantiateViewControllerWithIdentifier("EventCreate") as! EventCreate
eventcreatevc.modalPresentationStyle = .OverCurrentContext
self.presentViewController(eventcreatevc, animated: true, completion: nil)
//events.last!.annotation = pin
//events.last!.annotation.title = events.last!.eventName
//pin.title = events.last!.annotation.title
if events.isEmpty {
pin.title = "this is a test"
}
self.mapView.addAnnotation(pin)
print("added pin to map")
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.07, longitudeDelta: 0.07))
self.mapView.setRegion(region, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
let longpress = UILongPressGestureRecognizer(target: self, action: "addEvent:")
mapView.addGestureRecognizer(longpress)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EventCreate" {
var eventcreatevc = segue.destinationViewController as! EventCreate
}
}
override func viewWillAppear(animated: Bool) {
if events.isEmpty {
return
}
else {
for listofevent in events {
let pin = listofevent.annotation
self.mapView.addAnnotation(pin)
}
return
}
}
}
and
// EventCreate.swift
import UIKit
import MapKit
import CoreLocation
class EventCreate: UIViewController, UITextFieldDelegate, MKMapViewDelegate, UIGestureRecognizerDelegate {
// MARK: Properties
var name: String = ""
var loc: String = ""
var cost: Int = 0
var date: String = ""
var annot: MKPointAnnotation = MKPointAnnotation()
#IBOutlet weak var datePicker: UIDatePicker!
#IBOutlet weak var costSlider: UISlider!
#IBOutlet weak var locationTextField: UITextField!
#IBOutlet weak var locationLabel: UILabel!
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var costLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var eventNameLabel: UILabel!
#IBOutlet weak var createButton: UIButton!
// MARK: UITextFieldDelegate
func textFieldDidBeginEditing(textField: UITextField) {
createButton.enabled = false
}
func checkValidTextEntry(textField: UITextField) {
let text = textField.text ?? ""
createButton.enabled = !text.isEmpty
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
// hides the keyboard
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(textField: UITextField) {
if textField == nameTextField {
checkValidTextEntry(textField)
name = textField.text!
}
else if textField == locationTextField {
loc = textField.text!
}
}
func setAnnotation(annot: MKPointAnnotation) {
self.annot = annot
}
// MARK: Initialization
override func viewDidLoad() {
super.viewDidLoad()
nameTextField.delegate = self
locationTextField.delegate = self
checkValidTextEntry(nameTextField)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Actions
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if createButton === sender {
let event = Event(eventName: name, location: loc, cost: cost, date: date, annotation: annot)
events.append(event!)
}
}
}
Any help would be greatly appreciated!

Text from TextBox to Widget?

So i am making an iOS app, that lets you to enter text into a TextBox and then there is a Button that will display the "Text" on a label, and that "Text" on the label will be Displayed in the Notification Center, on a widget, But something is going wrong Because every time i run the app it fails and throws me into the AppDelegate.Swift and highlights me this specific part: "class AppDelegate: UIResponder, UIApplicationDelegate {"
with an error that says "Thread 1: signal SIGABRT"
i Don't know what else to do ;( please help!!
This is the ViewController.Swift code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var UserInput: UITextField!
#IBOutlet var TextDisplay: UILabel!
#IBAction func DisplayButton(sender: AnyObject) {
let Text:String = UserInput.text!
if let Text = Int(Text) {
print("Computer says no!")
} else {
TextDisplay.text = (Text)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let SharedDefaults = NSUserDefaults(suiteName: "group.St33v3n.TextOnWidget")
SharedDefaults?.setObject(UserInput, forKey: "StringKey")
SharedDefaults?.synchronize()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
and Here is the TodayView controller code (the one from the widget):
import UIKit
import NotificationCenter
class TodayViewController: UIViewController, NCWidgetProviding {
#IBOutlet var TextToWidget: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view from its nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
let ShareDefaults = NSUserDefaults(suiteName:"group.St33v3n.TextOnWidget")
self.TextToWidget.text = ShareDefaults?.objectForKey("StringKey") as? String
completionHandler(NCUpdateResult.NewData)
}
}
In the line
SharedDefaults?.setObject(UserInput, forKey: "StringKey")
you are passing UITextField object, not the text. You should use
SharedDefaults?.setObject(UserInput.text, forKey: "StringKey")
I'm not sure if that is causing the crash, but it needs correction anyway ;)

Resources