Add markers from UITableViewController to UIViewController - ios

I have a UIViewController, inside of this one in my storyboard I have a UITableViewController and a GMSMapView.
Well, I have a service to populate my UITableViewController, with some information and georeferences. The UITableViewController behavior is working perfectly, but when I try to access to my UIViewController the markers aren't added.
class RequestViewController: UIViewController {
#IBOutlet weak var mapView: GMSMapView!
var solicitudes = [SolicitudesModel]()
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 83.4824182, longitude: -88.1776567, zoom: 15)
self.mapView.camera = camera
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(13.4824182, -88.1776567)
marker.title = "My location"
marker.map = self.mapView
}
}
The marker as this point was added.
class RequestTableViewController: UITableViewController {
var reqs = [RequestModel]()
#IBOutlet var RequestTable: UITableView!
override func viewDidLoad() {
var requestVC = RequestViewController()
Alamofire.request(UrlGlobals.retriveInformation()).responseJSON { response in
let json = JSON(response.result.value)
var i: Int = 0
self.reqs.removeAll()
for _ in json.array ?? [] {
//Some code to populate the table
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(CLLocationDegrees(json["lat"].float!), CLLocationDegrees(json["lng"].float!))
marker.title = "Some title"
marker.map = requestVC.mapView
}
self.RequestTable.reloadData()
}
}
}
The json retrieves all the information correctly. How I can access to my primary ViewController and add those google markers?

Right now your RequestViewController is an instance that exists only in viewDidLoad. Make it a class property and you will be able to access it anywhere.

Related

Passing a Double between ViewControllers Swift 3

Total noob here to Swift 3. All I need to do is pass a double value from one ViewController to another via the 2 user input text fields. I've tried numerous solutions and have read everything I can find on passing data between ViewControllers. I get a 'fatal error: unexpectedly found nil while unwrapping an Optional value'. I have a real hard time understand the wrapping and unwrapping of the variables and I'm sure it's something simple.
Here is my first ViewController:
import UIKit
var longitude: Double?
var latitude: Double?
class ViewController: UIViewController {
#IBOutlet var getLongitude: UITextField!
#IBOutlet var getLatitude: UITextField!
#IBOutlet var mapbutton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func MapBtn(_ sender: Any) {
performSegue(withIdentifier: "segue", sender: self)
longitude = Double(getLongitude.text!)!
latitude = Double(getLatitude.text!)!
}
}
And this is the SecondViewController:
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: latitude!, longitude: longitude!, zoom: 6.0)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
// Creates a marker in the center of the map.
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: latitude!, longitude: longitude!)
marker.map = mapView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Avoid global mutable state. Send data from one scene to another.
Try this:
class ViewController: UIViewController {
#IBOutlet weak var longitudeTextField: UITextField!
#IBOutlet weak var latitudeTextField: UITextField!
#IBOutlet weak var mapButton: UIButton!
#IBAction func didTapToMapButton(_ sender: UIButton) {
// I assume your storyboard' name is Main. If not, change it below accordingly
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
// I assume your destination view controller' identifier and type is SecondViewController. If not, change it below accordingly.
if let secondViewController = mainStoryboard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController {
if let longitude = Double(longitudeTextField.text),
let latitude = Double(latitudeTextField.text) {
secondViewController.latitude = latitude
secondViewController.longitude = longitude
}
present(secondViewController, animated: true, completion: nil)
}
}
}
class SecondViewController: UIViewController {
var latitude: Double?
var longitude: Double?
override func viewDidLoad() {
super.viewDidLoad()
if let latitude = latitude,
let longitude = longitude {
let camera = GMSCameraPosition.camera(withLatitude: latitude, longitude: longitude, zoom: 6.0)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
// Creates a marker in the center of the map.
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
marker.map = mapView
}
}
}
1st, Unwrapping. when you try to unwrap the variable, rather forcely unwrap it, it's better test if it's nil, or you could use if let to safely unwrap it.
2nd, pass variable from one VC to another. As you know, in iOS, those VCs instances are like any other variable. All you need to do is trying to fetch a reference to that VC, then assign the Double to its accessible variable. Take a look at this link
You could create a segue between the two controllers and pass the variable by overriding prepare for segue.
Pass that variable to the new controller and load that information to its outlet on viewDidAppear or viewWillAppear.
self.prepare(for: "segueName", sender: self)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueName" {
if let vc = segue.destination as? DestinationViewController {
// Pass Data to New View Controller
}
}
}

Change CLLocationCoordinate2DMake With array by indexPath

Im trying to code the CLLocationCoordinate2DMake to change by an array so the lat and long will change depending on the indxPath ...
like i tried here:
var Longitude = ["32.101145","32.074961","",""]
var Latitude = ["34.775163","34.781679","","",""]
//What i tried :
let LightHouseLocation = CLLocationCoordinate2DMake(Longitude[indexPath.row],Latitude[indexPath.row])
// Drop a pin
but of course its throwing errors on me . i will be grateful if anyone could help me, Thank you .
This is how I would do it.
class ViewController: UIViewController {
#IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var coordinates = Array<CLLocationCoordinate2D>()
coordinates.append(CLLocationCoordinate2DMake(32.101145, 32.074961))
coordinates.append(CLLocationCoordinate2DMake(34.775163, 34.781679))
let pins = coordinates.map { (coordinate) -> MKPointAnnotation in
let pin = MKPointAnnotation()
pin.coordinate = coordinate
return pin
}
self.map.addAnnotations(pins)
}
}

Google Maps API IOS cannot load new coordinates with custom UIView

I have a problem with loading coordinates for a custom UIView that has been linked through IBOutlet and subclassed as GMSMapView. The mapView loads but it always shows the wrong location every time (always London as I presume that is the default). But if I change self.mapView to self.view, the coordinates load correctly within the map. I have no clue why loading coordinates with a custom UIView doesn't work while using the superview works. Thank you in advanced!
#IBOutlet var mapView: GMSMapView!
override func loadView() {
super.loadView()
let kCameraLatitude = 37.314617900000002
let kCameraLongitude = -121.7901318
let camera = GMSCameraPosition.cameraWithLatitude(kCameraLatitude,
longitude: kCameraLongitude, zoom: 1)
let newMapView = GMSMapView.mapWithFrame(self.mapView.frame, camera: camera)
self.mapView = newMapView
}
I had the same problem.
I fixed it by changing the view camera only as such:
#IBOutlet var mapView: GMSMapView!
override func loadView() {
super.loadView()
let kCameraLatitude = 37.314617900000002
let kCameraLongitude = -121.7901318
let camera = GMSCameraPosition.cameraWithLatitude(kCameraLatitude,
longitude: kCameraLongitude, zoom: 1)
self.mapView.camera = camera
}

Defining the title and the subtitle text of an annotation in Swift

I was watching a course on how to edit maps in Swift and add annotations, but unfortunately the instructor did not talk about how to edit the title and the subtitle of an annotation after adding one on the map, so I wanted to go a little bit further and edit them with my very simple knowledge in Swift.
Here's the code:
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
//add
#IBOutlet weak var titleText: UITextField!
#IBOutlet weak var subtitleText: UITextField!
#IBOutlet weak var buttonAdd: UIButton!
//add
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//add
subtitleText.alpha = 0
titleText.alpha = 0
buttonAdd.hidden = true
//add
// 51.498340, -0.153257
var latitude:CLLocationDegrees = 51.498340
var longitude:CLLocationDegrees = -0.153257
var latDelta:CLLocationDegrees = 0.02
var lonDelta:CLLocationDegrees = 0.02
var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
var location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
var region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
mapView.setRegion(region, animated: true)
var annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = "Belgravia"
annotation.subtitle = "I love you!"
mapView.addAnnotation(annotation)
var uilpgr = UILongPressGestureRecognizer(target: self, action: "action:")
uilpgr.minimumPressDuration = 2.0
mapView.addGestureRecognizer(uilpgr)
}
let newAnnotation = MKPointAnnotation()
func action(gestureRecognizer:UIGestureRecognizer) {
var touchPoint = gestureRecognizer.locationInView(self.mapView)
var newCoordinate:CLLocationCoordinate2D = mapView.convertPoint(touchPoint, toCoordinateFromView: self.mapView)
newAnnotation.coordinate = newCoordinate
titleText.alpha = 1
subtitleText.alpha = 1
buttonAdd.hidden = false
mapView.addAnnotation(newAnnotation)
var uilpgr = UILongPressGestureRecognizer(target: self, action: "action:")
uilpgr.minimumPressDuration = 2.0
}
func addPoint(sender: AnyObject) {
newAnnotation.title = titleText.text
newAnnotation.subtitle = subtitleText.text
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Every time I try to write text inside these two and then press the addPoint button in the iOS simulator it'll crash unexpectedly
[Maps.ViewController button:]: unrecognized selector sent to instance...

Unexpectedly found Nil unwrapping an Optional value

I am aware that there are many other questions like this however I assure you this is not a duplicate as far as I can tell. As you can see in the code below I have not marked any values as Optional however I keep getting this error. It crashes when I run the snapNext value highlighting the
viewMap.camera = newLocation
Here is the full code below, I have the viewMap linked to just a regular UIView
import UIKit
import MapKit
import GoogleMaps
class ViewController: UIViewController {
var camera = GMSCameraPosition.cameraWithLatitude(33.600727, longitude: -117.900840, zoom: 16.9)
#IBOutlet weak var viewMap: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
viewMap.camera = camera
viewMap = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
viewMap.myLocationEnabled = true
viewMap.settings.myLocationButton = true
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(33.600727, -117.900840)
marker.title = "Newport Beach"
marker.snippet = "California"
marker.map = viewMap
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func snapNext(sender: AnyObject) {
let newLocation = GMSCameraPosition.cameraWithLatitude(33.622578, longitude: -117.911099, zoom: 16.9)
viewMap.camera = newLocation
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your error is in the line:
viewMap = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
Here you are setting the map to a new anonymous object and because the map property is weak it will be set to nil automatically as soon as the anonymous object goes out of scope (i.e. when viewDidLoad completes).
Either you want to create the object in the storyboard; in which case leave it as a weak outlet, or you just want it as a 'normal' property; in which case remove the weak and IBOutlet.
import UIKit
import MapKit
import GoogleMaps
class ViewController: UIViewControllerGMSMapViewDelegate , CLLocationManagerDelegate {
var camera:GMSCameraPosition!
#IBOutlet weak var viewMap: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
camera = GMSCameraPosition.cameraWithLatitude(33.600727, longitude: -117.900840, zoom: 16.9)
viewMap.camera = camera
viewMap = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
viewMap.myLocationEnabled = true
viewMap.delegate=self
viewMap.settings.myLocationButton = true
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(33.600727, -117.900840)
marker.title = "Newport Beach"
marker.snippet = "California"
marker.map = viewMap
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func snapNext(sender: AnyObject) {
camera = GMSCameraPosition.cameraWithLatitude(33.622578, longitude: -117.911099, zoom: 16.9)
viewMap.camera = camera
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As you've already pointed out the viewMap is nil. Why it's getting released, I do not know (Need more info to know that). But I know that you can prevent it by removing the weak keyword.
#IBOutlet weak var viewMap: GMSMapView!
However, this might lead to leaks if you have retain cycles between your viewMap and your view controller.

Resources