send data back to previous controller from the second controller it displays Google autocomplete search Places - ios

Hello I have a button in FirstVC and in SecondVC I have a search box on navigationBar which is Google Autocomplete search bar in which user types something and it shows the places. What I want is when user clicks the button and secondVC comes, as soon user selects the place, the firstVC should show up with the data selected on secondVC without user presses any action Button.
Before implementing Google autocomplete, I was showing locations from database in TableView and I was redirecting user to first controller by writing some code in didSelectRowAtIndexPath and everything was working fine. its not working here. I'll Paste my code here of what I am doing right now
FirstVC:
class AddRequestTableViewController:GooglePlacesViewControllerDelegate{
func country(place: GMSPlace!) {
dismissKeyboard()
print("Place name: ", place.name)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let destination = segue.destinationViewController as! GooglePlacesViewController
destination.delegate = self
}
}
SecondVC
protocol GooglePlacesViewControllerDelegate {
func country(place: GMSPlace!,departureOrArrivalSegue:Int)
}
class GooglePlacesViewController: UIViewController {
var delegate : GooglePlacesViewControllerDelegate! = nil
var resultsViewController: GMSAutocompleteResultsViewController?
var searchController: UISearchController?
var resultView: UITextView?
var locationManager = CLLocationManager()
var placesClient : GMSPlacesClient?
var departureOrArrivalSegue:Int?
override func viewDidLoad() {
super.viewDidLoad()
//locationManager.startUpdatingLocation()
// locationManager = CLLocationManager()
// locationManager.delegate = self
//locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
//locationManager.startUpdatingLocation()
//locationManager.startMonitoringSignificantLocationChanges()
resultsViewController = GMSAutocompleteResultsViewController()
resultsViewController?.delegate = self
searchController = UISearchController(searchResultsController: resultsViewController)
searchController?.searchResultsUpdater = resultsViewController
// Put the search bar in the navigation bar.
searchController?.searchBar.sizeToFit()
self.navigationItem.titleView = searchController?.searchBar
// When UISearchController presents the results view, present it in
// this view controller, not one further up the chain.
self.definesPresentationContext = true
// Prevent the navigation bar from being hidden when searching.
searchController?.hidesNavigationBarDuringPresentation = false
let camera = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: Selector("btnOpenCamera"))
self.navigationItem.leftBarButtonItem = camera
placesClient = GMSPlacesClient()
run()
}
func run(){
placesClient?.currentPlaceWithCallback({
(placeLikelihoodList: GMSPlaceLikelihoodList?, error: NSError?) -> Void in
if let error = error {
print("Pick Place error: \(error.localizedDescription)")
return
}
if let placeLicklihoodList = placeLikelihoodList {
let place = placeLicklihoodList.likelihoods.first! as GMSPlaceLikelihood
if let place : GMSPlaceLikelihood = place {
print("place is \(place.place.formattedAddress)")
}
}
})
}
}
// Handle the user's selection.
extension GooglePlacesViewController: GMSAutocompleteResultsViewControllerDelegate {
func resultsController(resultsController: GMSAutocompleteResultsViewController!,
didAutocompleteWithPlace place: GMSPlace!) {
searchController?.active = false
// Do something with the selected place.
print("Place name: ", place.name)
print("Place address: ", place.formattedAddress)
print("Place attributions: ", place.attributions)
print("cordinates are \(place.coordinate)")
delegate.country(place)
}
func resultsController(resultsController: GMSAutocompleteResultsViewController!,
didFailAutocompleteWithError error: NSError!){
// TODO: handle the error.
print("Error: ", error.description)
}
// Turn the network activity indicator on and off again.
func didRequestAutocompletePredictionsForResultsController(resultsController: GMSAutocompleteResultsViewController!) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
func didUpdateAutocompletePredictionsForResultsController(resultsController: GMSAutocompleteResultsViewController!) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}
}

Your delegate method is:
func country(place: GMSPlace!,departureOrArrivalSegue:Int)
but you only called:
delgate.country(place)
Are you not recieving a compiler error? There should be another argument for your delegate call.
Also your 'GooglePlacesViewController' has not declared itself a delegate for the 'resultsViewController'. You called:
resultsViewController?.delegate = self
So your 'GooglePlacesViewController' should look something like this:
class GooglePlacesViewController: UIViewController, GMSAutocompleteResultsViewControllerDelegate {
How you aren't recieving compiler errors is beyond me. Are you using nano?

Related

use popToRootViewController and pass Data

I'm applying for a junior developer position and I've got a very specific task, that already took me 3 days to complete. Sounds easy - pass data to rootViewController.
That's what I've done:
1)
private func userDefaultsToRootController() {
let input = textField.text!
defaults.set(input, forKey: "SavedLabel")
navigationController?.popViewController(animated: true)
}
private func segueToRootViewController() {
let destinationVC = MainScreen1()
let input = textField.text!
if input == "" { self.navigationController?.popToRootViewController(animated: true) }
destinationVC.input = input
navigationController?.pushViewController(destinationVC, animated: true)
}
private func popToNavigationController() {
let input = textField.text!
if let rootVC = navigationController?.viewControllers.first as? MainScreen1 {
rootVC.input = input
}
navigationController?.popToRootViewController(animated: true)
}
I've used CoreData
But here is the difficult part - I've got an email, that all these methods are not good enough and I need to use delegate and closure. I've done delegation and closures before, but when I popToRootViewController delegate method passes nil. Could you at least point where to find info about this?
** ADDED **
There are 2 View Controllers: Initial and Second one.
That's what I have in the Initial View Controller:
var secondVC = MainScreen2()
override func viewDidLoad() {
super.viewDidLoad()
secondVC.delegate = self
}
That's how I push SecondViewController
#objc private func buttonTapped(_ sender: CustomButton) {
let nextViewController = MainScreen2()
navigationController?.pushViewController(nextViewController, animated: true)
}
In SecondViewController I've got this protocol
protocol PassData {
func transferData(text: String)
}
Also a delegate:
var delegate: PassData?
This is how I go back to initial view controller
#objc private func buttonTapped(_ sender: CustomButton) {
if let input = textField.text {
print(input)
self.delegate?.transferData(text: input)
self.navigationController?.popToRootViewController(animated: true)
}
}
Back to the Initial view controller where I've implemented delegate method
extension MainScreen1: PassData {
func transferData(text: String) {
print("delegate called")
label.text = text
}
}
Delegate doesn't get called.
BASED ON YOUR EDIT:
You must set the delegate in buttonTapped
#objc private func buttonTapped(_ sender: CustomButton) {
let nextViewController = MainScreen2()
nextViewController.delegate = self // HERE WHERE YOU SET THE DELEGATE
navigationController?.pushViewController(nextViewController, animated: true)
}
You can delete the second instance and your code in viewDidLoad. That's not the instance you push.
This should point you in the right direction to use delegation and completion handler.
protocol YourDelegateName {
func passData(data:YourDataType)
}
class SecondViewController: UIViewController {
var delegate: YourDelegateName?
func passDataFromSecondViewController(){
YourCoreDataClass.shared.getCoreData { (yourStringsArray) in
self.delegate?.passData(data: yourStringsArray)
self.navigationController?.popToRootViewController(animated: true)
}
}
class InitialViewController: UIViewController, YourDelegateName {
override func viewDidLoad() {
super.viewDidLoad()
// or whenever you instantiate your SecondViewController
let secondViewController = SecondViewController()
secondViewController.delegate = self //VERY IMPORTANT, MANY MISS THIS
self.navigationController?.pushViewController(createVC, animated: true)
}
func passData(data:YourDataType){
//user your data
}
}
class YourCoreDataClass: NSObject {
static let shared = YourCoreDataClass()
func getCoreData (completion: ([String]) -> ()){
........... your code
let yourStringsArray = [String]() // let's use as example an array of strings
//when you got the data your want to pass
completion(yourStringsArray)
}
}

MapKit map returns nil inside of function being called inside of different ViewController

I'm currently trying to implement a Map connected with a search function. For the overlay containing the table view, I've decided to go for a library called FloatingPanel.
I have to ViewControllers, namely MapViewController and SearchTableViewController - as the name already says, MapViewController contains a mapView. I assume since FloatingPanel adds SearchTableViewController (STVC) to MapViewController (MVC), that STVC is MVC's child.
Now whenever I want to call the MapViewController's function to add annotation inside of SearchTableViewController, MapViewController's mapView returns nil - calling it inside of MapViewController works fine.
class MapViewController: UIViewController, FloatingPanelControllerDelegate, UISearchBarDelegate {
var fpc: FloatingPanelController!
var searchVC = SearchResultTableViewController()
let locationManager = CLLocationManager()
let regionInMeters: Double = 10000
#IBOutlet private var mapView: MKMapView!
var mapItems: [MKMapItem]?
override func viewDidLoad() {
super.viewDidLoad()
checkLocationServices()
fpc = FloatingPanelController()
fpc.delegate = self
fpc.surfaceView.backgroundColor = .clear
fpc.surfaceView.cornerRadius = 9.0
fpc.surfaceView.shadowHidden = false
searchVC = (storyboard?.instantiateViewController(withIdentifier: "SearchPanel") as! SearchResultTableViewController)
fpc.set(contentViewController: searchVC)
fpc.track(scrollView: searchVC.tableView)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
fpc.addPanel(toParent: self, animated: true)
fpc.move(to: .tip, animated: true)
searchVC.searchController.searchBar.delegate = self
}
func checkLocationServices() {
if CLLocationManager.locationServicesEnabled() {
setupLocationManager()
checkLocationAuthorization()
} else {
}
}
func setupLocationManager() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
func checkLocationAuthorization() {
switch CLLocationManager.authorizationStatus() {
case .authorizedWhenInUse:
centerViewOnUserLocation()
break
case .denied:
break
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
break
case .restricted:
break
case .authorizedAlways:
break
#unknown default:
break
}
}
func centerViewOnUserLocation() {
if let location = locationManager.location?.coordinate {
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
mapView.setRegion(region, animated: true)
}
}
#IBAction func click(_ sender: Any) {
}
func addPin(title: String, subtitle: String, coordinates: CLLocationCoordinate2D) {
let destination = customPin(pinTitle: title, pinSubTitle: subtitle, location: coordinates)
mapView.addAnnotation(destination)
}
func addAnnotationToMap() {
guard let item = mapItems?.first else { return }
guard let coordinates = item.placemark.location?.coordinate else { return }
addPin(title: item.name!, subtitle: "", coordinates: coordinates)
}
}
SearchTableViewController's function:
func passData() {
guard let mapViewController = storyboard?.instantiateViewController(withIdentifier: "map") as? MapViewController else { return }
guard let mapItem = places?.first else { return }
mapViewController.mapItems = [mapItem]
mapViewController.addAnnotationToMap()
}
This
guard let mapViewController = storyboard?.instantiateViewController(withIdentifier: "map") as? MapViewController else { return }
guard let mapItem = places?.first else { return }
creates a new seperate object other than the actual one that you have to access , use delegate to do it here
searchVC = (storyboard?.instantiateViewController(withIdentifier: "SearchPanel") as! SearchResultTableViewController)
searchVC.delegate = self // here
fpc.set(contentViewController: searchVC)
then declare
weak var delegate:MapViewController?
inside SearchViewController and use it
func passData() {
guard let mapItem = places?.first else { return }
delegate?.mapItems = [mapItem]
delegate?.addAnnotationToMap()
}
Several things:
When you use a third party library in your project and your readers might want to know about that library in order to understand your problem, you should include a link to the library in your question. I did a Google search and was able to find what I think is the correct library.
The sample code for that library has you call fpc.addPanel() in your view controller's viewDidLoad(), not in viewDidAppear().
The viewDidLoad() function is only called once in the lifetime of a view controller, but viewDidAppear() is called every time a view controller get's re-shown (like when it is redisplayed after being covered by a modal and then uncovered again.) The two are not interchangeable for that reason. I suggest moving that call back to viewDidLoad().
Next, as others have mentioned, your SearchTableViewController's passData() function is wrong. It creates a new, throw-away MapViewController every time it is called. It does not talk to the hosting MapViewController at all.
You should refactor your viewDidLoad() to set up the MapViewController as the delegate of the SearchTableViewController.
Define a protocol (possibly in a separate file
protocol SearchTableViewControllerDelegate {
var mapItems: [MapItem] //Or whatever type
func addAnnotationToMap()
}
Some changes to MapViewController
class MapViewController:
SearchTableViewControllerDelegate,
UIViewController,
FloatingPanelControllerDelegate,
UISearchBarDelegate {
//Your other code...
}
override func viewDidLoad() {
super.viewDidLoad()
checkLocationServices()
fpc = FloatingPanelController()
fpc.delegate = self
fpc.surfaceView.backgroundColor = .clear
fpc.surfaceView.cornerRadius = 9.0
fpc.surfaceView.shadowHidden = false
searchVC = (storyboard?.instantiateViewController(withIdentifier: "SearchPanel") as! SearchResultTableViewController)
//--------------------------
searchVC.delegate = self //This new line is important
//--------------------------
fpc.set(contentViewController: searchVC)
fpc.track(scrollView: searchVC.tableView)
fpc.addPanel(toParent: self) //Probably can't be animated at this point
}
And in SearchTableViewController:
class SearchTableViewController: UITableViewController, <Other protocols> {
weak var delegate: SearchTableViewControllerDelegate?
// other code...
func passData() {
guard let mapItem = places?.first else { return }
delegate?.mapItems = [mapItem]
delegate?.addAnnotationToMap()
}
}
You're instantiating a new MapViewController instead if passing data to the one that exists. There are three ways to do this:
Delegation
Closures
Notifications
An example using a closure, in SearchViewController:
var passData: ((MKMapItem) -> ())?
In MapViewController provide it a closure:
searchVC = (storyboard?.instantiateViewController(withIdentifier: "SearchPanel") as! SearchResultTableViewController)
searchVC.passData = { mapItem in
self.mapItems = [mapItem]
}
In SearchViewController call the closure:
passData?(mapItem)

Why does the second view controller didn´t appear after loading the entry view, but by clicking on a button, he does?

Why does the second view controller didn´t appear after loading the entry view, but by clicking on a button, he does?
Here is my code:
#IBAction func Pressed(_ sender: UIButton) {
var firstName = FirstName.text;
var lastName = LastName.text;
let defaults = UserDefaults.standard;
defaults.set(firstName, forKey: "FN");
defaults.set(lastName, forKey: "LN");
loadNextView()
}
override func viewDidLoad() {
super.viewDidLoad()
self.FirstName.text = "TESTAUSGABE";
let defaults = UserDefaults.standard;
var fn = defaults.object(forKey: "FN")
var ln = defaults.object(forKey: "LN")
if(fn==nil){
self.FirstName.placeholder="Nicht angegeben"
}
else {
self.FirstName.text = fn as? String
loadNextView()
}
if(ln==nil){
self.LastName.placeholder="Nicht angegeben"
}
else{
self.LastName.text = ln as? String
self.Pressed(self.SaveButton);
}
}
func loadNextView(){
let storyboard: UIStoryboard = UIStoryboard(name:"Main", bundle:nil);
let newViewControler = storyboard.instantiateViewController(withIdentifier: "View2") as UIViewController
self.present(newViewControler, animated: true, completion: nil)
}
I want to check the preferences and if they are already set then it should appear automatically another view.
Or is there another method I didn't know?
Prsenting VCs doesn't work inside viewDidLoad as the view hierarchy is not yet complete , You can try to implement viewDidAppear or viewWillAppear
var runOnce = true
//
override func viewDidAppear(_ animated:Bool){
super.viewDidAppear(animated)
if runOnce {
loadNextView() // here read default value
runOnce = false
}
}

Add initial note

I am looking at adding an inital note to the note page within my app. this is so that when people click to the notes part there will be some detail on how to use it rather than just a big empty screen. I have no idea where to implement this though. Could you please help, below is the page where it talks about the dictionaries.
import UIKit
import MessageUI
class DetailViewController: UIViewController, MFMailComposeViewControllerDelegate, UITextViewDelegate {
#IBOutlet weak var tView: UITextView!
#IBAction func BarButton(sender: UIBarButtonItem) {
let textToShare = ""
if let myWebsite = NSURL(string: "")
{
let objectsToShare = [textToShare, myWebsite]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
self.presentViewController(activityVC, animated: true, completion: nil)
}
OpenMail()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tView.text = (allNotes[currentNoteIndex] as Note).note
tView.becomeFirstResponder()
// Set controller as swipe gesture recogniser, to allow keyboard dismissal for text box
var swipe: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "dismissKeyboard")
swipe.direction = UISwipeGestureRecognizerDirection.Down
self.view.addGestureRecognizer(swipe)
self.tView.delegate = self
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if tView.text == "" {
allNotes.removeAtIndex(currentNoteIndex)
}
else {
(allNotes[currentNoteIndex] as Note).note = tView.text
}
Note.saveNotes()
noteTable?.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func configuredMailComposeViewController() -> MFMailComposeViewController {
// Open mail controller on screen and prepare with preset values.
let mailComposerVC = MFMailComposeViewController()
var MessageText: String!
MessageText = tView.text
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients([""])
mailComposerVC.setSubject("")
mailComposerVC.setMessageBody(MessageText, isHTML: false)
return mailComposerVC
}
func showSendMailErrorAlert() {
// Alert user to email error
let sendMailErrorAlert = UIAlertView(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", delegate: self, cancelButtonTitle: "OK")
sendMailErrorAlert.show()
}
// MARK: MFMailComposeViewControllerDelegate Method
func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
controller.dismissViewControllerAnimated(true, completion: nil)
}
func OpenMail() {
//Function to open mail composer on screen
let mailComposeViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.presentViewController(mailComposeViewController, animated: true, completion: nil)
} else {
self.showSendMailErrorAlert()
}
}
func dismissKeyboard() {
// Dismiss keyboard for textfield
self.tView.resignFirstResponder()
}
}
note.swift
import UIKit
var allNotes:[Note] = []
var currentNoteIndex:NSInteger = -1
var noteTable:UITableView?
let KAllNotes:String = "notes"
class Note: NSObject {
var date:String
var note:String
override init() {
date = NSDate().description
note = ""
}
func dictionary() -> NSDictionary {
return ["note":note, "date":date]
}
class func saveNotes() {
var aDictionaries:[NSDictionary] = []
for (var i:NSInteger = 0; i < allNotes.count; i++) {
aDictionaries.append(allNotes[i].dictionary())
}
NSUserDefaults.standardUserDefaults().setObject(aDictionaries, forKey: KAllNotes)
// aDictionaries.writeToFile(filePath(), atomically: true)
}
class func loadnotes() {
allNotes.removeAll(keepCapacity: true)
var defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
var savedData:[NSDictionary]? = defaults.objectForKey(KAllNotes) as? [NSDictionary]
// var savedData:NSArray? = NSArray(contentsOfFile: filePath())
if let data:[NSDictionary] = savedData {
for (var i:NSInteger = 0; i < data.count; i++) {
var n:Note = Note()
n.setValuesForKeysWithDictionary(data[i] as [NSObject : AnyObject])
allNotes.append(n)
}
}
}
class func filePath() -> String {
var d:[String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if let directories:[String] = d {
var docsDirectory:String = directories[0]
var path:String = docsDirectory.stringByAppendingPathComponent("\(KAllNotes).notes")
return path;
}
return ""
}
}
Thanks in advance
Sam
Add an NSUserDefault boolean that stores whether or not the initial note should be shown, e.g. that the app has been launched for the first time. Then load an initial note accordingly. When a note is added or the initial note is deleted, then change the boolean accordingly so the initial note doesn't show up next time.
You could also initialize your database with an initial note. Not clear from your code how the notes are saved, but this approach would probably rely on the NSUserDefault approach above, except it could be done in the AppDelegate or something.
example:
let InitialSetupComplete = "InitialSetupComplete" // Note: I would define this at the top of a file
let defaults = NSUserDefaults.standardUserDefaults()
if defaults.boolForKey(InitialSetupComplete) {
// Show initial note
}
// Later on when the note is deleted, or modified (or immediately after initial note loaded into the database, see below)
defaults.setBool(true, forKey: InitialSetupComplete)
Would be easier/cleaner just to initialize your database with the initial note in the app delegate (e.g. call within applicationDidFinishLaunching), so your view controller doesn't have to figure this out. Similar code, except you would use setBool right away after the initial note has been saved to the database. I don't know anything about your database from the question, so can't really provide a more detailed example than this. Hope this helps.

Protocols and Delegates in Swift

I have two View Controllers: "DiscoverViewController" and "LocationRequestModalViewController".
The first time a user opens the "DiscoverViewController", I overlay "LocationRequestModalViewController" which contains a little blurb about accessing the users location data and how it can help them.
On the "LocationRequestModalViewController" there are two buttons: "No thanks" and "Use location". I need to send the response from the user back to the "DiscoverViewController"
I have done some research and found that delegates/protocols are the best way to do it, so I followed a guide to get that working, but I'm left with 2 errors and can't figure them out.
The errors are:
On DiscoverViewController
'DiscoverViewController' is not convertible to 'LocationRequestModalViewController'
On LocationRequestModalViewController
'LocationRequestModalViewController' does not have a member name 'sendBackUserLocationDataChoice'
I've marked where the errors are happen in the following files:
DiscoverViewController.swift
class DiscoverViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, LocationRequestModalViewControllerDelegate {
func showLocationRequestModal() {
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var locationRequestVC: AnyObject! = storyboard.instantiateViewControllerWithIdentifier("locationRequestVC")
self.presentingViewController?.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
self.tabBarController?.presentViewController(locationRequestVC as UIViewController, animated: true, completion: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let vc = segue.destinationViewController as LocationRequestModalViewController
vc.delegate = self //This is where error 1 happens
}
func sendBackUserLocationDataChoice(controller: LocationRequestModalViewController, useData: Bool) {
var enableData = useData
controller.navigationController?.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
showLocationRequestModal()
}
}
LocationRequestModalViewController
protocol LocationRequestModalViewControllerDelegate {
func sendBackUserLocationDataChoice(controller:LocationRequestModalViewController,useData:Bool)
}
class LocationRequestModalViewController: UIViewController {
var delegate:LocationRequestModalViewController? = nil
#IBAction func dontUseLocationData(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func useLocationData(sender: AnyObject) {
delegate?.sendBackUserLocationDataChoice(self, useData: true) // This is where error #2 happens
}
override func viewDidLoad() {
super.viewDidLoad()
//Modal appearance stuff here...
}
}
The answer is in your question itself. Both errors tells the exact reason.
Issue 1
let vc = segue.destinationViewController as LocationRequestModalViewController
vc.delegate = self //This is where error 1 happens
The self is of type DiscoverViewController
But you declared the delegate as:
var delegate:LocationRequestModalViewController? = nil
You need to change that to:
var delegate:DiscoverViewController? = nil
Issue 2
The same reason, LocationRequestModalViewController does not confirm to the LocationRequestModalViewControllerDelegate, change the delegate declaration.
You have defined your delegate as having type LocationRequestModalViewController which does not conform to LocationRequestModalViewControllerDelegate.

Resources