Parse PFGeoPoint save location getting started - swift

Im trying to create an app with two user types...one sends a location and the other user type (on a different device) searches an area and finds the closest user.
I have been on parse's website and stack overflow...they all seem to start in the middle. I would like to have somebody explain the first steps
Heres my code
import UIKit
import MapKit
import CoreLocation
import Parse
class ViewController: UIViewController, MKMapViewDelegate,
CLLocationManagerDelegate, UISearchBarDelegate,
UIGestureRecognizerDelegate
{
#IBOutlet weak var photographer1: UIButton!
#IBOutlet weak var buyer1: UIButton!
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var searchBar: UISearchBar!
let locationManager = CLLocationManager()
var searchController:UISearchController!
var annotation:MKAnnotation!
var localSearchRequest:MKLocalSearchRequest!
var localSearch:MKLocalSearch!
var localSearchResponse:MKLocalSearchResponse!
var error:NSError!
var pointAnnotation:MKPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
override func viewDidLoad()
{
super.viewDidLoad()
self.locationManager.delegate = self
self.mapView.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
}
// to run the animation this sec of code checks if the region was changed
var mapChangedFromUserInteraction = false
func mapViewRegionDidChangeFromUserInteraction() -> Bool {
let view = self.mapView.subviews[0]
// Look through gesture recognizers to determine whether this region change is from user interaction
if let gestureRecognizers = view.gestureRecognizers {
for recognizer in gestureRecognizers {
if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {
return true
}
}
}
return false
}
func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
if (mapChangedFromUserInteraction) {
// user changed map region
}
}
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if (mapChangedFromUserInteraction) {
hobo()
//
buyer1.center = CGPointMake(188.0, 513.0)
photographer1.center = CGPointMake(188.0, 581.0)
}
}
// your boy
// MARK: - Location Delegate Methods
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.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print("Error: " + error.localizedDescription)
}
func searchBarSearchButtonClicked(searchBar: UISearchBar){
//1
searchBar.resignFirstResponder()
dismissViewControllerAnimated(true, completion: nil)
if self.mapView.annotations.count != 0{
annotation = self.mapView.annotations[0]
self.mapView.removeAnnotation(annotation)
}
//2
localSearchRequest = MKLocalSearchRequest()
localSearchRequest.naturalLanguageQuery = searchBar.text
localSearch = MKLocalSearch(request: localSearchRequest)
localSearch.startWithCompletionHandler { (localSearchResponse, error) -> Void in
if localSearchResponse == nil{
let alertController = UIAlertController(title: nil, message: "Place Not Found", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
return
}
//3
self.pointAnnotation = MKPointAnnotation()
self.pointAnnotation.title = searchBar.text
self.pointAnnotation.coordinate = CLLocationCoordinate2D(latitude: localSearchResponse!.boundingRegion.center.latitude, longitude: localSearchResponse!.boundingRegion.center.longitude)
self.pinAnnotationView = MKPinAnnotationView(annotation: self.pointAnnotation, reuseIdentifier: nil)
self.mapView.centerCoordinate = self.pointAnnotation.coordinate
self.mapView.addAnnotation(self.pinAnnotationView.annotation!)
}
}
func hobo(){
print("testing")
}
#IBAction func showSearchBar(sender: AnyObject) {
searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
self.searchController.searchBar.delegate = self
presentViewController(searchController, animated: true, completion: nil)
}
#IBAction func locateMe(sender: AnyObject) {
self.mapView.showsUserLocation = true
self.locationManager.startUpdatingLocation()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
buyer1.center = CGPointMake(188.0, 581.0)
photographer1.center = CGPointMake(188.0, 513.0)
}
#IBAction func photographer(sender: AnyObject) {
}
#IBAction func buyer(sender: AnyObject) {
}
}

Related

The centre locations in MapKit is not visible in the UiLabel

Unable to show the centrelocation of map in the label!
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var myMapView: MKMapView!
#IBOutlet weak var addressLabel: UILabel!
let locationManager = CLLocationManager()
let regionInMeters: Double = 10000
var previousLocation: CLLocation?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
checkLocationServices()
}
func setupLocationManager() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
func centerViewOnUserLocation() {
if let location = locationManager.location?.coordinate {
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
myMapView.setRegion(region, animated: true)
}
}
// the Location service
func checkLocationServices() {
if CLLocationManager.locationServicesEnabled() {
setupLocationManager()
checkLocationAuthorisation()
} else {
//show user to turn ON the services
}
}
func checkLocationAuthorisation() {
switch CLLocationManager.authorizationStatus() {
case .authorizedWhenInUse:
// do the stuff
startTrackingLocation()
case .denied:
//Alert to turn ON the permissions
break
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .restricted:
// Alert to show what's up
break
case .authorizedAlways:
break
}
}
func startTrackingLocation() {
myMapView.showsUserLocation = true
centerViewOnUserLocation()
locationManager.startUpdatingLocation()
previousLocation = getCenterLocation(for: myMapView)
}
func getCenterLocation(for mapView: MKMapView) -> CLLocation {
let latitude = mapView.centerCoordinate.latitude
let longitude = mapView.centerCoordinate.longitude
return CLLocation(latitude: latitude, longitude: longitude)
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// We'll be back
checkLocationAuthorisation()
}
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let center = getCenterLocation(for: myMapView)
let geoCoder = CLGeocoder()
guard let previousLocation = self.previousLocation else { return }
guard center.distance(from: previousLocation) > 50 else { return }
self.previousLocation = center
geoCoder.reverseGeocodeLocation(center) { [weak self] (placemarks, error) in
guard let self = self else { return }
if let _ = error {
//TODO: Show alert informing the user
return
}
guard let placemark = placemarks?.first else {
//TODO: Show alert informing the user
return
}
let streetNumber = placemark.subThoroughfare ?? ""
let streetName = placemark.subThoroughfare ?? ""
DispatchQueue.main.async {
self.addressLabel.text = "\(streetNumber) \(streetName)"
}
}
}
#IBAction func satelliteView(_ sender: Any) {
myMapView.mapType = MKMapType.satellite
}
#IBAction func hybridView(_ sender: Any) {
myMapView.mapType = MKMapType.hybrid
}
#IBAction func standardView(_ sender: Any) {
myMapView.mapType = MKMapType.standard
}
#IBAction func findDirections(_ sender: Any) {
}
}
The label in the app is supposed to show the centrelocation(pin) of the map. But don't know for where is it going wrong!
Changed the getCenterlocation function and its working fine!
`func getCenterLocation(for mapView: MKMapView) -> CLLocation {
let latitude=mapView.centerCoordinate.latitude
let longitude=mapView.centerCoordinate.longitude
return CLLocation(latitude:latitude, longitude:longitude)
}
func getCenterLocation(for myMapView: MKMapView) -> CLLocation {
let latitude=myMapView.centerCoordinate.latitude
let longitude=myMapView.centerCoordinate.longitude
return CLLocation(latitude:latitude, longitude:longitude)
}`

In Swift, IBOutlet unexpectly found nil on self delegate?

This problem is absolutely driving me insane, and I've searched all over with no luck finding a solution. Please forgive what is probably a basic question...
I followed a tutorial to make a simple Geofence application. Problem is, my MKMapView keeps giving me a nil variable when I declare it, giving me the "unexpectedly found nil while unwrapping an Optional value" error.
The variable in question is mapView, and the line that's giving me an issue is mapView.delegate = self
Here's my code:
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// setup locationManager
locationManager.delegate = self
locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters
locationManager.desiredAccuracy = kCLLocationAccuracyBest
// setup mapView
mapView.delegate = self
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
// setup test data
setupData()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// status is not determined
if CLLocationManager.authorizationStatus() == .notDetermined {
locationManager.requestAlwaysAuthorization()
}
// authorization were denied
else if CLLocationManager.authorizationStatus() == .denied {
showAlert(title: "Location services were previously denied. Please enable location services for this app in Settings.")
}
// we do have authorization
else if CLLocationManager.authorizationStatus() == .authorizedAlways {
locationManager.startUpdatingLocation()
}
}
func setupData() {
// check if can monitor regions
if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
// region data
let title = "Weber"
let coordinate = CLLocationCoordinate2DMake(37.703026, -121.759735)
let regionRadius = 300.0
// setup region
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude), radius: regionRadius, identifier: title)
locationManager.startMonitoring(for: region)
// setup annotation
let restaurantAnnotation = MKPointAnnotation()
restaurantAnnotation.coordinate = coordinate;
restaurantAnnotation.title = "\(title)";
mapView.addAnnotation(restaurantAnnotation)
// setup circle
let circle = MKCircle(center: coordinate, radius: regionRadius)
mapView.add(circle)
}
else {
print("System can't track regions")
}
}
// MARK: - MKMapViewDelegate
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.strokeColor = UIColor.blue
circleRenderer.lineWidth = 1.0
return circleRenderer
}
// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
showAlert(title: "enter \(region.identifier)")
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
showAlert(title: "exit \(region.identifier)")
}
// MARK: - Helpers
func showAlert(title: String) {
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}

Swift- segue between views with map annotation button

I relatively new to programming and need help switching between views by tapping a button in a mapView annotated pin.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
//REF
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var bottompnl: UIImageView!
#IBAction func mysticsbtn(sender: AnyObject) {
}
#IBAction func bondibtn(sender: AnyObject) {
}
//MAP
let locationManager = CLLocationManager()
//Annotation
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
let identifier = "beach"
if annotation is Beach {
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
let btn = UIButton(type: .DetailDisclosure)
annotationView!.rightCalloutAccessoryView = btn
} else {
annotationView!.annotation = annotation
}
return annotationView
self.performSegueWithIdentifier("mysticssegue", sender: nil)
}
return nil
}
override func viewDidLoad() {
super.viewDidLoad()
let annotations = getMapAnnotations()
// Add mappoints to Map
mapView.addAnnotations(annotations)
mapView.delegate = self
//MAP
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
//MAKES THE DOT
self.mapView.showsUserLocation = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MAP: Location Delegates Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let centre = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: centre, span: MKCoordinateSpan(latitudeDelta: 3, longitudeDelta: 3))
self.mapView.setRegion(region, animated: true)
self.locationManager.startUpdatingLocation()
}
//TO FIND ERROS
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Erros: " + error.localizedDescription)
}
//MARK:- Annotations
func getMapAnnotations() -> [Beach] {
var annotations:Array = [Beach]()
//load plist file
var beaches: NSArray?
if let path = NSBundle.mainBundle().pathForResource("beaches", ofType: "plist") {
beaches = NSArray(contentsOfFile: path)
}
if let items = beaches {
for item in items {
let lat = item.valueForKey("lat") as! Double
let long = item.valueForKey("long")as! Double
let annotation = Beach(latitude: lat, longitude: long)
annotation.title = item.valueForKey("title") as? String
annotations.append(annotation)
}
}
return annotations
}
//END
}
It looks like you're returning from the function mapView before calling performSegueWithIdentifier.
return annotationView
self.performSegueWithIdentifier("mysticssegue", sender: nil)
Try reversing the order of these two lines. I also noticed that you have some #IBAction methods that have no code in them.

How to detect zoom's effect on the map in Swift

I am using regionDidChangeAnimated for my mapView. I want to detect when user zoom's or drag's a map. Drag is being detected, but I can't seem to detect when user zoom's the map. I tried to use:
func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
print("region will change")
}
But when I zoom my map it does not work.
Full code:
var locationManager: CLLocationManager = CLLocationManager()
var startLocation: CLLocation!
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
//get current location
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
startLocation = nil
let mapDragRecognizer = UIPanGestureRecognizer(target: self, action: "didDragMap:")
mapDragRecognizer.delegate = self
self.mapView.addGestureRecognizer(mapDragRecognizer)
self.mapView.pitchEnabled = true
self.mapView.showsBuildings = true
}
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.05, longitudeDelta: 0.05))
mapView.setRegion(region, animated: false)
let currentLocX = String(format: "%.4f", location!.coordinate.latitude)
let currentLocY = String(format: "%.4f", location!.coordinate.longitude)
self.locationManager.stopUpdatingLocation()
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Errors: " + error.localizedDescription)
}
func didDragMap(gestureRecognizer: UIGestureRecognizer) {
print("Drag")
}
func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
print("Zoom")
}
I have solved it. In the override func viewDidLoad() need to add self.mapView.delegate = self
And add functions for determine zoom's on the map:
private var mapChangedFromUserInteraction = false
private func mapViewRegionDidChangeFromUserInteraction() -> Bool {
let view = self.mapView.subviews[0]
if let gestureRecognizers = view.gestureRecognizers {
for recognizer in gestureRecognizers {
if( recognizer.state == UIGestureRecognizer.State.began || recognizer.state == UIGestureRecognizer.State.ended )) {
return true
}
}
}
return false
}
func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
}
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if (mapChangedFromUserInteraction) {
print("ZOOM finished")
}
}

-swift- trouble passing parse object from map kit annotation to detailViewController using disclosure button in swift

Please help, Im having trouble passing parse object from annotation Query to destinationViewController. When the user taps the annotation view it takes the user to the destinationVC, but it passes the same object no matter which annotation the user taps. I think it has something to do with the prepareForSegue function. Please let me know what Im doing wrong.
Heres my code:
class MapSearchViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var jobPosts = [PFObject]()
var jobPost: PFObject?
let locationManager = CLLocationManager()
var currentLoc: PFGeoPoint! = PFGeoPoint()
override func viewDidLoad() {
super.viewDidLoad()
//MARK new added code Start--
self.mapView.delegate = self
self.mapView.setUserTrackingMode(MKUserTrackingMode.Follow, animated: true)
//MARK new added code End--
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
//Snippet For Blue Current Location Dot:
//self.mapView.showsUserLocation = true
}
//MARK: -- Location Delegate Methods
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: NSError) {
print("Errors: " + error.localizedDescription)
}
//MARK: OCT 26
override func viewDidAppear(animated: Bool) {
let annotationQuery = PFQuery(className: "JobPost")
currentLoc = PFGeoPoint(location: locationManager.location)
annotationQuery.whereKey("location", nearGeoPoint: currentLoc, withinMiles: 100)
annotationQuery.findObjectsInBackgroundWithBlock {
(posts, error) -> Void in
if error == nil {
// The find succeeded.
print("Successful query for annotations")
let jobPosts = posts as [PFObject]!
for post in jobPosts {
let point = post["location"] as! PFGeoPoint
var annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude)
self.mapView.addAnnotation(annotation)
annotation.title = post["job"] as! String
let pay = post["price"] as! String
let payLabel = "\(pay)$"
annotation.subtitle = payLabel
let btn = UIButton(type: .DetailDisclosure)
self.jobPost = post
}
} else {
// Log details of the failure
print("Error: \(error)")
}
}
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
var view = mapView.dequeueReusableAnnotationViewWithIdentifier("annotationIdentifier")
if view == nil {
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "annotationIdentifier")
view?.canShowCallout = true
view?.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
} else {
view?.annotation = annotation
}
return view
}
var selectedAnnotation: MKPointAnnotation!
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
selectedAnnotation = view.annotation as? MKPointAnnotation
performSegueWithIdentifier("annotationSender", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let destination = segue.destinationViewController as? JobDetailViewController {
destination.currentObject = jobPost
}
}
}
code for detailVC:
class JobDetailViewController: UIViewController, MFMailComposeViewControllerDelegate {
#IBOutlet weak var jobTitleLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var distanceLabel: UILabel!
#IBOutlet weak var jobDescriptionContent: UITextView!
#IBOutlet weak var pictureImageView: UIImageView!
var jobPosts:[PFObject]!
var currentObject : PFObject?
var distance = "7"
var annotation = MKPointAnnotation()
override func viewDidLoad() {
super.viewDidLoad()
self.distanceLabel.text = "\(distance) miles away"
if let object = currentObject {
jobTitleLabel.text = object["job"] as! String
priceLabel.text = object["price"] as! String
jobDescriptionContent.text = object["description"] as! String
}
}