您如何让位置捕获器在覆盖转场之前运行?

Posted

技术标签:

【中文标题】您如何让位置捕获器在覆盖转场之前运行?【英文标题】:How do you get a location capturer to run before an override segue? 【发布时间】:2020-10-23 15:02:34 【问题描述】:

因此,我需要在用户访问主页之前捕获用户的位置(当然要获得他们的许可)。因此,在登录/注册页面上,我想捕获该位置,但我需要在将登录用户覆盖到主页之前执行此操作。你们有什么想法吗?下面是覆盖segue。

我将位置捕获器放在覆盖功能中的 segue 之前,但在用户有机会接受共享位置之前它仍然进入主页。这并不是真正的意外,因为整个覆盖函数根据定义是一个覆盖函数

  override func viewDidAppear(_ animated: Bool) 
//////////////////////
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])   

    let databaseRef = Database.database().reference()
    guard let uid = Auth.auth().currentUser?.uid else  return 
    guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else  return 
    print("locations = \(locValue.latitude) \(locValue.longitude)")
    latestLocation = ["latitude" : locValue.latitude, "longitude" : locValue.longitude]
    let lat = locValue.latitude
    let lon = locValue.longitude
    dict = CLLocation(latitude: lat, longitude: lon)
    print("dict", dict)
    if let locationDictionary = latestLocation            
databaseRef.child("people").child(uid).child("Coordinates").setValue(locationDictionary)  
       

//////////////////////
 if  Auth.auth().currentUser != nil 
        self.performSegue(withIdentifier: "tohome", sender: nil)
    

更新:这是我登录和注册的方式。

    @IBAction func RegisterPressed(_ sender: Any) 
        
        Auth.auth().createUser(withEmail: (emailField.text ?? ""), password: (passwordField.text ?? ""))   (user, error) in
            if let _eror = error 
                //something bad happning
                print(_eror.localizedDescription )
                let alert = UIAlertController(title: "Error", message: "Invalid Entry or Duplicate.", preferredStyle: UIAlertController.Style.alert)
                let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
                alert.addAction(action)
                self.present(alert, animated: true, completion: nil)
                
            else
                //user registered successfully
                print(user as Any)
                if let userID = user?.user.uid
                
                    KeychainWrapper.standard.set((userID), forKey: "uid")
                    
                    let databaseRef = Database.database().reference()
                    
                    databaseRef.child("A1").child(userID).child("users").setValue(self.emailField.text!)
                    databaseRef.child("people").child(userID).child("postID").setValue(userID)
                    let components = self.emailField.text!.split(separator: "@")
                    let child1 = components[0] //will be jake
                    let child2 = components[1] //will be aol.com
                    print(components, child1, child2, "childs")
                    databaseRef.child("people").child(userID).child("e2").setValue(child2)


                    components.forEach  print($0) 
                    
                    
                    

                    
                    self.performSegue(withIdentifier: "tohome", sender: nil)
                
                
            
        
    
     @IBAction func loginInPressed(_ sender: Any) 
 Auth.auth().signIn(withEmail: (emailField.text ?? ""), password: (passwordField.text ?? ""))   (user, error) in
    if let _eror = error 
                   //something bad happning
                   print(_eror.localizedDescription )
                let alert = UIAlertController(title: "Error", message: "Incorrect Email or Password.", preferredStyle: UIAlertController.Style.alert)
                                     let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
                                     alert.addAction(action)
                                     self.present(alert, animated: true, completion: nil)

               else
                   //user registered successfully
                   print(user as Any)
                        if let userID = user?.user.uid
 
                            KeychainWrapper.standard.set((userID), forKey: "uid")
                            self.performSegue(withIdentifier: "tohome", sender: nil) 

               
            
    

【问题讨论】:

【参考方案1】:

如果我在viewDidAppear(_:) 中理解正确,您有一个条件。如果是true,您会立即尝试执行转场。

if  Auth.auth().currentUser != nil 
    self.performSegue(withIdentifier: "tohome", sender: nil)

由于位置必须移动到HomeScreen,当您在CLLocationManagerDelegate 内收到第一个位置更新时,为什么不进行导航(segue)?

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])   
      // check for existing location if we received earlier
      guard self.latestLoc == nil else 
         // we received one location earlier, navigation to Home completed. no need to proceed 
         // If we no longer need to listen for loc updates, we can stop listening further
         manager.stopUpdatingLocation()
         return
       
      // ... Your exiting data base update code
     guard let latestLoc = locations.last else  return 
     self.latestLoc = latestLoc // If you want to pass this location to destination view controller in `prepare(for: UIStoryboardSegue, sender: Any?)`
     // Also it will good practice to call manager.stopUpdatingLocation() if you need location only for once 

     // Now move to HomeScreen
     self.performSegue(withIdentifier: "tohome", sender: nil)

     // If we no longer need to listen for loc updates, we can stop listening further
     manager.stopUpdatingLocation()

【讨论】:

嗯,这可能有效。在这种情况下,您将如何将 latestLoc 定义为 CLLocation?至于它是否传递给目标VC;我不认为本身。这会在 firebase 中注册用户的位置。在“toHome”之后,下一页使用该 firebase 条目 我将它定义为 CLLocation 并且它似乎有效。唯一的问题是关于prepare(for: UIStoryboardSegue, sender: Any?) 如果我将所有代码放在override func prepare(for: UIStoryboardSegue, sender: Any?) 中,在说允许之后它不会自动继续。如果我不使用prepare(for: UIStoryboardSegue, sender: Any?),在加载下一页(segue 指向的)之前是否仍会使用该位置? 我测试了它,它工作正常。唯一的问题是有时它会在主屏幕(tohome 的目的地)上重新加载两次。它以前从未这样做过。我认为这与先前构建的缓存有关,这是首先要解决的问题。还是你觉得跟prepare(for: UIStoryboardSegue, sender: Any?)有关系? 因此您现在面临一个新问题,即从您正在收听位置更新的屏幕上连续两次HomeScreen。如果是这种情况,您可以简单地检查您是否已经从以前的委托回调中获得了位置。 self.latestLoc = latestLoc 通过这个你可以保存最新的位置。如果您已经收到位置并且屏幕导航已经完成,您可以提前返回。 谢谢。这是有道理的,但是您将 latestLoc 定义为什么?它不能是 CLLocation 原因,然后它给出错误 Comparing non-optional value of type 'CLLocation' to 'nil' always returns false 它是否必须是一个字符串?

以上是关于您如何让位置捕获器在覆盖转场之前运行?的主要内容,如果未能解决你的问题,请参考以下文章

在 BigQuery 中加载 JSON / JSON 在从位置开始的行中解析错误 ...:解析器在字符串结束之前终止

动画后执行 Segue,但动画项目回到之前的位置

如何捕获位置警报响应iphone

如何在记录位置之前等待 GPS 定位

CSS JQuery 位置选择器在 IE 上为空

如何使用 Autodesk Forge 查看器在 3D 模型中查找位置(x、y、z 坐标)