Segue 加载下一个屏幕两次
Segue Loads Next Screen Twice
我四处搜索但似乎无法找到为什么我的 segue 会两次加载下一个视图控制器的答案。出于某种原因,它只是偶尔发生,我会说按下 getMyLocation
按钮的大约 1/5 次。我想要发生的是用户按下 getMylocation
并从那里获取用户的坐标、存储数据,并使用存储的数据呈现下一个视图。因此,我在 didUpdatedLocations
中有 performSegue
以便我可以在调用 segue 之前存储数据。我应该注意到,segue 是通过按住 ctrl 单击并将我的主视图拖到下一个视图而不是通过拖动按钮在故事板中创建的。
我的代码先看第一个:
// Declare all IB Outlets
@IBOutlet weak var cityLabel: SpringTextField!
@IBOutlet weak var stateLabel: SpringTextField!
@IBOutlet weak var searchButton: SpringButton!
@IBOutlet weak var getLocationButton: SpringButton!
@IBOutlet weak var locationButton: UIButton!
@IBOutlet weak var citySearchButton: UIButton!
// Declare all variables
var latAndLong = ""
var city = ""
var state = ""
let locationManager = CLLocationManager()
let limitLength = 2
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
let lat = locValue.latitude
let long = locValue.longitude
latAndLong = "\(lat),\(long)"
locationManager.stopUpdatingLocation()
self.performSegue(withIdentifier: "goToSecond", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
// Declare text label delegates to allow control
cityLabel.delegate = self as UITextFieldDelegate
stateLabel.delegate = self as UITextFieldDelegate
// Define what tap to look for
let tap : UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
// Delgate Location Manager
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
}
// Allow keyboard to switch text fields from city to state by pressing return
internal func textFieldShouldReturn(_ textField : UITextField) -> Bool {
if textField == cityLabel {
city = cityLabel.text!
textField.resignFirstResponder()
stateLabel.becomeFirstResponder()
}
if textField == stateLabel {
state = stateLabel.text!
performSegue(withIdentifier: "goToSecond", sender: self)
}
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var newLength = 0
if textField == stateLabel {
guard let text = textField.text else { return true }
newLength = text.count + string.count - range.length
return newLength <= 2
}
else if textField == cityLabel {
guard let text = textField.text else { return true }
newLength = text.count + string.count - range.length
return newLength <= 40
}
return true
}
// Location manager required function + store location variables + perform transition to next view
// Defines what happens when either "Get My Location" or "Search by city is pressed"
@IBAction func getMyLocationPressed(_ sender: Any) {
city = ""
state = ""
let status = CLLocationManager.authorizationStatus()
if status == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
}
else if status == .notDetermined {
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
return
}
else if status == .denied || status == .restricted {
let alert = UIAlertController(title : "Location Services Disabled", message: "Please enable location, or search by City and State", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK",style: .default, handler: nil)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
return
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("didnt work")
}
@IBAction func getLocationPressed(_ sender: SpringButton) {
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined {
locationManager.requestWhenInUseAuthorization()
return
}
else if status == .denied || status == .restricted {
let alert = UIAlertController(title : "Location Services Disabled", message: "Please enable location, or search by City and State", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK",style: .default, handler: nil)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
return
}
locationManager.startUpdatingLocation()
}
// Defines what happens during transition to next screen including what variables to send ober
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToSecond" {
let nextVC = segue.destination as! SecondViewController
nextVC.cityAndState = (city) + "," + (state)
nextVC.latAndLong = latAndLong
}
}
}
我的第二个视图代码:
var latAndLong = ""
var cityAndState = ""
@IBOutlet weak var tableView: UITableView!
var selectedRow = ""
var namesOfPictures = ["Activities-1", "Food", "Drinks", "Random"]
let display = ["Activities", "Food", "Drink", "Random"]
let cellColors = ["#4D606E","#3FBAC2","#D3D4D8","#F5F5F5"]
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
tableView.separatorStyle = .singleLine
tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "realCell")
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "realCell", for: indexPath) as! TableViewCell
cell.backgroundView = UIImageView(image: UIImage(named: namesOfPictures[indexPath.row]))
cell.label.text = display[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return display.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(latAndLong)
selectedRow = display[indexPath.row]
print(selectedRow)
tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "goToActivities", sender: self)
}
func configureTableView() {
tableView.rowHeight = 152.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToActivities" {
let nextVC = segue.destination as! ActivitiesViewController
nextVC.selectedItem = selectedRow
nextVC.cityAndState = cityAndState
nextVC.latAndLong = latAndLong
}
}
CLLoction 管理器委托 - "didUpdateLocations:" 即使在停止位置更新后也会多次触发
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
获取有效用户位置后必须将委托设置为 nil
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//After validating user location
locationManager.delegate = nil
我四处搜索但似乎无法找到为什么我的 segue 会两次加载下一个视图控制器的答案。出于某种原因,它只是偶尔发生,我会说按下 getMyLocation
按钮的大约 1/5 次。我想要发生的是用户按下 getMylocation
并从那里获取用户的坐标、存储数据,并使用存储的数据呈现下一个视图。因此,我在 didUpdatedLocations
中有 performSegue
以便我可以在调用 segue 之前存储数据。我应该注意到,segue 是通过按住 ctrl 单击并将我的主视图拖到下一个视图而不是通过拖动按钮在故事板中创建的。
我的代码先看第一个:
// Declare all IB Outlets
@IBOutlet weak var cityLabel: SpringTextField!
@IBOutlet weak var stateLabel: SpringTextField!
@IBOutlet weak var searchButton: SpringButton!
@IBOutlet weak var getLocationButton: SpringButton!
@IBOutlet weak var locationButton: UIButton!
@IBOutlet weak var citySearchButton: UIButton!
// Declare all variables
var latAndLong = ""
var city = ""
var state = ""
let locationManager = CLLocationManager()
let limitLength = 2
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
let lat = locValue.latitude
let long = locValue.longitude
latAndLong = "\(lat),\(long)"
locationManager.stopUpdatingLocation()
self.performSegue(withIdentifier: "goToSecond", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
// Declare text label delegates to allow control
cityLabel.delegate = self as UITextFieldDelegate
stateLabel.delegate = self as UITextFieldDelegate
// Define what tap to look for
let tap : UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
// Delgate Location Manager
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
}
// Allow keyboard to switch text fields from city to state by pressing return
internal func textFieldShouldReturn(_ textField : UITextField) -> Bool {
if textField == cityLabel {
city = cityLabel.text!
textField.resignFirstResponder()
stateLabel.becomeFirstResponder()
}
if textField == stateLabel {
state = stateLabel.text!
performSegue(withIdentifier: "goToSecond", sender: self)
}
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var newLength = 0
if textField == stateLabel {
guard let text = textField.text else { return true }
newLength = text.count + string.count - range.length
return newLength <= 2
}
else if textField == cityLabel {
guard let text = textField.text else { return true }
newLength = text.count + string.count - range.length
return newLength <= 40
}
return true
}
// Location manager required function + store location variables + perform transition to next view
// Defines what happens when either "Get My Location" or "Search by city is pressed"
@IBAction func getMyLocationPressed(_ sender: Any) {
city = ""
state = ""
let status = CLLocationManager.authorizationStatus()
if status == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
}
else if status == .notDetermined {
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
return
}
else if status == .denied || status == .restricted {
let alert = UIAlertController(title : "Location Services Disabled", message: "Please enable location, or search by City and State", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK",style: .default, handler: nil)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
return
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("didnt work")
}
@IBAction func getLocationPressed(_ sender: SpringButton) {
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined {
locationManager.requestWhenInUseAuthorization()
return
}
else if status == .denied || status == .restricted {
let alert = UIAlertController(title : "Location Services Disabled", message: "Please enable location, or search by City and State", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK",style: .default, handler: nil)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
return
}
locationManager.startUpdatingLocation()
}
// Defines what happens during transition to next screen including what variables to send ober
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToSecond" {
let nextVC = segue.destination as! SecondViewController
nextVC.cityAndState = (city) + "," + (state)
nextVC.latAndLong = latAndLong
}
}
}
我的第二个视图代码:
var latAndLong = ""
var cityAndState = ""
@IBOutlet weak var tableView: UITableView!
var selectedRow = ""
var namesOfPictures = ["Activities-1", "Food", "Drinks", "Random"]
let display = ["Activities", "Food", "Drink", "Random"]
let cellColors = ["#4D606E","#3FBAC2","#D3D4D8","#F5F5F5"]
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
tableView.separatorStyle = .singleLine
tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "realCell")
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "realCell", for: indexPath) as! TableViewCell
cell.backgroundView = UIImageView(image: UIImage(named: namesOfPictures[indexPath.row]))
cell.label.text = display[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return display.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(latAndLong)
selectedRow = display[indexPath.row]
print(selectedRow)
tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "goToActivities", sender: self)
}
func configureTableView() {
tableView.rowHeight = 152.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToActivities" {
let nextVC = segue.destination as! ActivitiesViewController
nextVC.selectedItem = selectedRow
nextVC.cityAndState = cityAndState
nextVC.latAndLong = latAndLong
}
}
CLLoction 管理器委托 - "didUpdateLocations:" 即使在停止位置更新后也会多次触发
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
获取有效用户位置后必须将委托设置为 nil
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//After validating user location
locationManager.delegate = nil