简体   繁体   中英

Swift sending data from child view to parent view controller

I am developing an app where I have a view controller and subview. On the subview I am loading Google maps and on the main view I have a label.

My question is how can I pass data from the subview (map geo location) to the label on the main view and have this updated as the location is updated using Swift.

All the tutorials I have found use prepareForSegue where I would like to just update the label automatically as it is on the main view.

Thanks

Updated: I can't seem to get the delegate method to work. Code below.

MapChildController.swift

import UIKit

protocol ChildViewControllerDelegate{
    func delegateMethod(childViewController:MapChildController, text:String)
}

class MapChildController: UIViewController, CLLocationManagerDelegate {

@IBOutlet weak var mapView: GMSMapView!
let locationManager = CLLocationManager()
var didFindMyLocation = false
var myLocations: [CLLocation] = []

var delegate:ChildViewControllerDelegate?

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    var camera = GMSCameraPosition.cameraWithLatitude(-33.86, longitude: 151.20, zoom: 15, bearing: 0, viewingAngle: 45)
    var mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)

    mapView.myLocationEnabled = true
    self.view = mapView

    locationManager.delegate = self
    locationManager.distanceFilter = kCLDistanceFilterNone
    locationManager.desiredAccuracy = kCLLocationAccuracyBest

    if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 8, minorVersion: 0, patchVersion: 0)) {
        println("iOS >= 8.0.0")
        locationManager.requestWhenInUseAuthorization()
        //locationManager.requestAlwaysAuthorization()
    }

    mapView.addObserver(self, forKeyPath: "myLocation", options: NSKeyValueObservingOptions.New, context: nil)

    locationManager.startUpdatingLocation()
    //locationManager.startMonitoringSignificantLocationChanges()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
    if !didFindMyLocation {
        let myLocation: CLLocation = change[NSKeyValueChangeNewKey] as! CLLocation
        var mapView = self.view as! GMSMapView
        mapView.camera = GMSCameraPosition.cameraWithTarget(myLocation.coordinate, zoom: 15.0)
        mapView.settings.myLocationButton = true
        didFindMyLocation = true
    }
}

func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject]) {

    // println("Last location: \(locations.last)")
    self.delegate?.delegateMethod(self, text: "from child")
}
}

MapController.swift

import Foundation
import UIKit

class MapController : UIViewController, ChildViewControllerDelegate
{
@IBOutlet weak var Label: UILabel!
var LabelText = String()

override func viewDidLoad() {
    super.viewDidLoad()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func delegateMethod(controller: MapChildController, text: String) {
    println("The text is " +  text);
}
}

Delegation pattern is your friend.

Declare a protocol on your child view controller that the parent view controller will implement. Whenever you want, call a method on the delegate reference you are holding in the child view controller - this will update the parent view controller with data from child VC.

This SO question explains the child parent delegation neatly How do I set up a simple delegate to communicate between two view controllers?

I see some answers here, so you can solve your problem changing some lines in your code, look at:

protocol ChildViewControllerDelegate{
    func delegateMethod(childViewController:MapChildController, text:String)
}

I used without the childViewController passing by method then you could just pass whatever you want send to another view just saying what type of data you want send, in case it's a String. So you can change the ChildViewControllerDelegate to:

protocol ChildViewControllerDelegate{
    func delegateMethod(text:String)
}

You need do the same thing in class MapController :

func delegateMethod(text: String) {
    println("The text is " +  text);
}

You can see a better explanation in: How to send data back by popViewControllerAnimated for Swift

var delegate:ChildViewControllerDelegate?

除此之外,您还需要这样做才能使委托工作:

delegate = MapController()
 self.navigationController?.popViewController(animated: true)
        let vc = self.navigationController?.viewControllers.last as! MainViewController
        vc.textfield.text = "test"

you can do like if you want maybe you dont need this answer but other users for useful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM