Firebase - 在类变量中保存唯一ID并将其数据发送到另一个控制器 - Swift

时间:2016-09-12 19:32:24

标签: ios swift firebase segue firebase-realtime-database

我使用childByAutoID使用firebase创建了一个唯一的ID。我可以在用于创建它的引用函数中打印此ID,但是当我将值赋给类变量并在控制台中打印它时,它会出现nil。

我正在尝试使用override func prepareForSegue方法将此数据发送到另一个视图控制器。当数据是字符串时它起作用,但当它是包含uniqueIDKey的变量时它不起作用。

以下是代码:

class MainViewController: UIViewController, CLLocationManagerDelegate{

    var ref: FIRDatabaseReference!
    var refHandle: UInt!
    let locationManager = CLLocationManager()
    let regionRadius: CLLocationDistance = 1000
    var currentLocation: CLLocation!
    var location: CLLocationCoordinate2D!
    var latitude: Double!
    var longitude: Double!
    let geoCoder = CLGeocoder()
    var placemark: CLPlacemark?
    let date = NSDate()
    var currentOrderIDKey = ""



    @IBOutlet weak var mapView: MKMapView!
    @IBOutlet weak var userEmailLabel: UILabel!
    @IBOutlet weak var pickUpAddress: UITextField!
    @IBOutlet weak var deliveryAddress: UITextField!

    override func viewDidLoad() {
        ref = FIRDatabase.database().reference()



        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.requestLocation()
        locationManager.startUpdatingLocation()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest




        refHandle = ref.observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in
            let dataDict = snapshot.value as! [String: AnyObject]

            print((dataDict))
        })
        let userID: String = FIRAuth.auth()!.currentUser!.uid
        ref.child("users").child(userID).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
        let userEmail = snapshot.value!["email"] as! String
        self.userEmailLabel.text = userEmail
        })


        super.viewDidLoad()
        print("\(currentLocation)")
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("didFailWithError \(error)")

        if error.code == CLError.LocationUnknown.rawValue {
            return
        }
    }

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

        currentLocation = locations.last!
        latitude = currentLocation.coordinate.latitude
        longitude = currentLocation.coordinate.longitude
        location = CLLocationCoordinate2DMake(latitude, longitude)

        print("didUpdateLocations \(currentLocation.coordinate)")

        if currentLocation.timestamp.timeIntervalSinceNow < -10 {
            return
        }
        let coordinateRegion = MKCoordinateRegionMakeWithDistance(location, regionRadius * 2.0, regionRadius * 2.0)
        mapView.setRegion(coordinateRegion, animated: false)
    }





    @IBAction func requestPickUpButton(sender: AnyObject) {
        ref = FIRDatabase.database().reference()
        let userID: String = FIRAuth.auth()!.currentUser!.uid
        ref.child("users").child(userID).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
        let orderRef = self.ref.child("users").child(userID).child("orders")
        let origin = self.pickUpAddress.text!
        let destination = self.deliveryAddress.text!
        let orderID = orderRef.childByAutoId()
        let formatter = NSDateFormatter();
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ";
        let defaultTimeZoneStr = formatter.stringFromDate(self.date)
        let order = ["date": defaultTimeZoneStr, "origin": origin, "destination": destination]
        orderID.setValue(order)
        self.currentOrderIDKey = orderID.key as String
        print(self.currentOrderIDKey) ///This works!
        self.performSegueWithIdentifier("ServiceConfirmation", sender: self)
        self.locationManager.stopUpdatingLocation()
        })

        print(currentOrderIDKey) //this doesnt
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "ServiceConfirmation" {
            let destinationConroller = segue.destinationViewController as! UINavigationController
            let targetController = destinationConroller.topViewController as! ServiceConfirmationViewController
            targetController.currentOrderIDKey = "this works"
          //this does not :   targetController.currentOrderIDKey = currentOrderIDKey
        }
    }


    @IBAction func signOutButton(sender: AnyObject) {
        try! FIRAuth.auth()!.signOut()
        if let storyboard = self.storyboard {
            let viewController = storyboard.instantiateViewControllerWithIdentifier("LoginViewController")
            self.presentViewController(viewController, animated: false, completion: nil)
        }
    }
}

作为一个额外的问题,我每次运行应用程序时都会在控制台中收到此警告:

<UILayoutContainerView: ...; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: ....>; layer = <CALayer: ....>>'s window is not equal to <UINavigationController: ....>'s view's window!

提前致谢!

1 个答案:

答案 0 :(得分:1)

这是 Asynchrounous 来电的另一个经典案例,即使在分配之前,您也会在currentOrderIDKey中访问print(currentOrderIDKey)的值。

即使在

之前,您的print(currentOrderIDKey)行也会被调用
self.currentOrderIDKey = orderID.key as String
    print(self.currentOrderIDKey) ///This works!

被召唤。

ref.child("users").child(userID).observeSingleEventOfType(.Value,..向您的后端发送 Asynchronous 调用,这需要一些时间来检索数据,但即使在您检索到数据之前,您的print(currentOrderIDKey)也会获得调用导致null

使用实例化而不是通过performSegue....进行隔离: -

let secondScene = self.navigationController?.storyboard?.instantiateViewControllerWithIdentifier("ServiceConfirmationViewControllerVC_ID") as! ServiceConfirmationViewController

  secondScene.valueTranfered = self. currentOrderIDKey
  self.navigationController?.pushViewController(secondScene, animated: true)

ServiceConfirmationViewControllerVC_ID 是你的secondScene storyBoardID

我建议您阅读此内容: - Wikipedia : Asynchronous calls&amp; https://stackoverflow.com/a/748189/6297658