I have many different buttons like UIStepper and DatePicker and a MapView. Can anyone help me get my whole view controller and the button working. I have been getting an error about SIGABRT. It say's "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Field_Service_Report.AddController hoursStepper:]: unrecognized selector sent to instance 0x7fb5d7c8d010'"
This is my View Controller code :
import UIKit
import MapKit
import CoreLocation
class AddController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var hoursStepperResult: UILabel!
#IBOutlet weak var hoursStepper: UIStepper!
#IBOutlet weak var minutesStepperResult: UILabel!
#IBOutlet weak var minutesStepper: UIStepper!
#IBOutlet weak var currentLocationLabel: UILabel!
#IBOutlet weak var dateOfReport: UIDatePicker!
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Start Map Contents
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
// End Map Contents
}
// Start Stepper Contents
#IBAction func hoursStepperAction(_ sender: UIStepper) {
hoursStepperResult.text = String(Int(sender.value))
}
#IBAction func minutesStepperAction(_ sender: UIStepper) {
minutesStepperResult.text = String(Int(sender.value))
}
// End Stepper Contents
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Here is the new code its giving me 3 erroe because im trying to get the text and numbers from another ViewController to print out in this VC.
#IBAction func doneACButton(_ sender: AnyObject) {
let newVC = storyboard?.instantiateViewController(withIdentifier: "ResultController") as! ResultController
newVC.intPassed = hoursIntProvided
newVC.intPassed = minutesIntProvided
newVC.stringPassed = resultedHours.text!
}
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: 1, longitudeDelta: 1))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Errors: " + error.localizedDescription)
}
// MARK: - Navigation
}
Notice the colon right here in the method signature:
-[Field_Service_Report.AddController hoursStepper:]
^
This is the signature of a method that takes a parameter, not the signature of an accessor. Are you sure you didn't misspell a selector name somewhere or leave something accidentally connected in IB that should have been removed? (Perhaps if you renamed a method and forgot to redo the action connection?)
Related
So I have a map view(mapkit based) and a slider in my storyboard. As the user slides, map zooms in or out based on their action. How do I implement that? I think that might have something to do with longitudeDelta and latitudeDelta.
Please help me.
import UIKit
import MapKit
import CoreLocation
class ConfigureViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapkitView: MKMapView!
#IBOutlet weak var travelRadius: UILabel!
#IBAction func button(sender: AnyObject) {
}
#IBAction func sliderChanged(sender: AnyObject) {
let sliderValue = lrintf(sender.value)
travelRadius.text = "\(sliderValue) mi."
let delta = Double(self.sliderChanged(sender.value))
var currentRegion = self.mapkitView.region
currentRegion.span = MKCoordinateSpan(latitudeDelta: delta, longitudeDelta: delta)
self.mapkitView.region = currentRegion
}
let locationManager = CLLocationManager()
#IBOutlet weak var mapKitView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapKitView.showsUserLocation = true
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
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: 1.5,
longitudeDelta: 1.5))
self.mapKitView.setRegion(region, animated: false)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print ("Errors:" + error.localizedDescription)
}
}
Screenshot of my storyboard
You set the zoom via the region property of the mapView. It defines both the center point of the map and the span (i.e. zoom level)
Edit
Do yourself a favor and define a separate IBOutlet for the slider. It turns out that your slider is measured in miles, but the span is measured in degrees latitude and longitude. How long 1 degree of latitude/longitude is in terms of miles vary depend on your location on Earth. Wikipedia has some discussion on latitude and longitude. Assuming you are on the equator, the conversion is 69 miles per degree of both.
(Remember to connect the outlets)
class ViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var slider: UISlider!
#IBOutlet weak var travelRadius: UILabel!
#IBOutlet weak var currentLocationLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
sliderChanged(self) // Set the correct zoom according to the slider initial value
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func sliderChanged(sender: AnyObject) {
let miles = Double(self.slider.value)
let delta = miles / 69.0
var currentRegion = self.mapView.region
currentRegion.span = MKCoordinateSpan(latitudeDelta: delta, longitudeDelta: delta)
self.mapView.region = currentRegion
travelRadius.text = "\(Int(round(miles))) miles"
let (lat, long) = (currentRegion.center.latitude, currentRegion.center.longitude)
currentLocationLabel.text = "Current location: \(lat), \(long))"
}
}
I am working on a small map application, so far I have the code to drop map pins and save them so they remain once the app is reopened, this class is for the main view controller:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UISearchBarDelegate, UIPopoverPresentationControllerDelegate {
var location: CLLocation!
let locationManager = CLLocationManager()
#IBOutlet weak var placesMap: MKMapView!
#IBOutlet weak var addButton: UIBarButtonItem!
#IBOutlet weak var moreStuff: UIButton!
// Popover button action
#IBAction func moreStuff(sender: AnyObject) {
self.performSegueWithIdentifier("showMoreStuff", sender:self)
moreStuff.adjustsImageWhenHighlighted = false
}
#IBAction func addButton(sender: AnyObject) {
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: self.placesMap.userLocation.coordinate.latitude, longitude: self.placesMap.userLocation.coordinate.longitude)
self.placesMap.addAnnotation(annotation)
self.locationManager.startUpdatingLocation()
}
// Location function
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.004, longitudeDelta: 0.004))
self.placesMap?.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
let locationDictionary:[String:Double] = ["latitude":center.latitude,"longitude":center.longitude]
var locationArray = [[String:Double]]()
if NSUserDefaults.standardUserDefaults().objectForKey("locationArray") != nil {
locationArray = NSUserDefaults.standardUserDefaults().objectForKey("locationArray") as! [[String:Double]]
}
locationArray.append(locationDictionary)
NSUserDefaults.standardUserDefaults().setObject(locationArray, forKey: "locationArray")
NSUserDefaults.standardUserDefaults().synchronize()
}
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.placesMap?.showsUserLocation = true
if NSUserDefaults.standardUserDefaults().objectForKey("locationArray") != nil {
for dictionary in NSUserDefaults.standardUserDefaults().objectForKey("locationArray") as! [[String:Double]]{
let center = CLLocationCoordinate2D(latitude: dictionary["latitude"]!, longitude: dictionary["longitude"]!)
let annotation = MKPointAnnotation()
annotation.coordinate = center
self.placesMap?.addAnnotation(annotation)
}
}
}
I want to add a button which allows all pins (memories) to be reset at once. This button is located on a new scene and class, called "PopoverOptions". I have the following code from the class which should do this, but it does not seem to be functioning as no pins disappear from the map once it is pressed by the user!
#IBOutlet weak var resetMemories: UIButton!
#IBAction func resetMemories(sender: AnyObject) {
func removeStoredLocations(){
NSUserDefaults.standardUserDefaults().removeObjectForKey("locationArray")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
Any idea why the pins aren't being removed? I have ensured that the class is linked correctly as well as the buttons outlet / action.
You clear out your user defaults key, but don't change the map view on the view controller that shows those pins. You need to call removeAnnotations to remove the annotations from the map.
You could add a viewWillAppear method that detects that your annotations have been deleted and remove them. Something like this:
func viewWillAppear(_ animated: Bool)
{
if NSUserDefaults.standardUserDefaults().objectForKey("locationArray") == nil
{
if let annotations = self.placesMap.annotations
self.placesMap?.removeAnnotations(annotations)
}
}
The code above is written to only remove the annotations from the map if the entire annotations dictionary was deleted from userDefaults. That way you avoid reloading the annotations every time the view controller regains focus.
BTW, you said your new scene is called "PopoverOptions." If the scene is presented in a popover then the above might not work. (I don't think viewWillAppear gets called on a view controller when a popover is dismissed, but I don't remember for sure.)
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!
I try to make an application in Swift 2 that displays all the GPS informations.
I can recover latitute, longitue, horizontalAccuracy, verticalAccuracy, altitude, distance and cap but I am unable to recover speed, whereas I arrived in Objective-C :-(
Thanks for your help
Below is my code:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var running = false
var pause = false
var locationManager: CLLocationManager = CLLocationManager()
var startLocation: CLLocation!
#IBOutlet weak var latitudeLabel: UILabel!
#IBOutlet weak var longitudeLabel: UILabel!
#IBOutlet weak var horizontalAccuracyLabel: UILabel!
#IBOutlet weak var verticalAccuracyLabel: UILabel!
#IBOutlet weak var capLabel: UILabel!
#IBOutlet weak var altitudeLabel: UILabel!
#IBOutlet weak var partielLabel: UILabel!
#IBOutlet weak var distanceLabel: UILabel!
#IBOutlet weak var vitesseLabel: UILabel!
#IBOutlet weak var moyenneLabel: UILabel!
#IBOutlet weak var timerLabel: UILabel!
#IBOutlet weak var totalDistanceLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
startLocation = nil
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func startDistance(sender: AnyObject) {
startLocation = nil
running = true
}
#IBAction func stopDistance(sender: AnyObject) {
running = false
}
#IBAction func resetDistance(sender: AnyObject) {
startLocation = nil
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let latestLocation: AnyObject = locations[locations.count - 1]
latitudeLabel.text = String(format: "%.4f",latestLocation.coordinate.latitude)
longitudeLabel.text = String(format: "%.4f",latestLocation.coordinate.longitude)
horizontalAccuracyLabel.text = String(format: "%.4f",latestLocation.horizontalAccuracy)
verticalAccuracyLabel.text = String(format: "%.4f",latestLocation.verticalAccuracy)
altitudeLabel.text = String(format: "%.4f",latestLocation.altitude)
if running == true {
if startLocation == nil {
startLocation = latestLocation as! CLLocation
}
let distanceBetween: CLLocationDistance =
latestLocation.distanceFromLocation(startLocation)
distanceLabel.text = String(format: "%.2f", distanceBetween)
}
}
func locationManager(manager: CLLocationManager, didUpdateHeading newHeading: CLHeading)
{
capLabel.text = String(format: "%.4f",newHeading.magneticHeading)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
}
}
I tested this code :
vitesseLabel.text = String(CLLocationSpeed())
but speed remains at 0.00
I finally found, so here's the code:
var speed: CLLocationSpeed = CLLocationSpeed()
speed = locationManager.location!.speed
vitesseLabel.text = String(format: "%.0f km/h", speed * 3.6)
The reason you don't know the speed is that you have not written any code where you ask the CLLocation for its speed.
I've tried following simple CoreLocation examples using Swift, but I'm unable to get things working. I've extracted most of the code out, so it's just barebones in order to focus the question, and I'm hoping the answer jumps out quickly to someone.
import UIKit
import CoreLocation
class ViewController: UIViewController,CLLocationManagerDelegate {
#IBOutlet weak var txtLatitude: UITextField!
#IBOutlet weak var txtLongitude: UITextField!
#IBOutlet weak var cmdLocateMe: UIButton!
#IBOutlet weak var slider: UISlider!
#IBOutlet weak var txtSlider: UITextField!
#IBOutlet weak var power: UISwitch!
var locationManager: CLLocationManager!
override func viewDidLoad() {
locationManager = CLLocationManager();
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation();
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.
}
#IBAction func valueChanged(sender: UISlider) {
if power.on{
var val = "\(slider.value)";
txtSlider.text = val;
}
}
#IBAction func cmdLocateMeClicked(sender: UIButton) {
}
//Deprecated
#IBAction func cmdLocateMePressed(sender: AnyObject) {
}
//CLLocationManagerDelegate
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var location:CLLocation = locations[locations.count-1] as CLLocation
println("locations = \(locations)")
txtLatitude.text = "\(location.coordinate.latitude)";
txtLongitude.text = "\(location.coordinate.longitude)";
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println(error)
txtLatitude.text = "Can't get your location!"
}
}
Figured it out -- I had to give permissions to my app to receive Location Information on the iOS Simulator (Settings -> Privacy -> Location). Once I did that, things worked perfectly.