在执行代码之前等待用户关闭模态视图 (Swift 2.0)
Wait for user to dismiss Modal View before executing code (Swift 2.0)
我正在构建一个应用程序,如果用户不允许使用 模态呈现 的模式访问他们当前的位置,则要求用户select 一个位置一旦用户点击 'Deny'。此模态将信息显示为 TableView,一旦用户 select 一行,模态就会消失。我将这个 selection 保存在一个名为 selectedStop
的变量中。 我希望应用程序暂停,直到用户 select 找到一个位置,然后一旦用户 select 找到一个位置,应用程序就会继续并执行 setUpMap() 函数.我尝试在 setUpMap() 中使用无限 while
循环,并在用户 select 连续使用布尔值时立即跳出它,但是 while 循环甚至在 Modal 弹出之前执行.
ViewController.swift
class ViewController: UIViewController {
var selectedStop: Int!
override func viewDidLoad() {
super.viewDidLoad()
// If we don't have access to the user's current location, request for it
if (CLLocationManager.authorizationStatus() != CLAuthorizationStatus.AuthorizedWhenInUse) {
locationManager.requestWhenInUseAuthorization()
}
}
func setUpMap() {
// do stuff with var selectedStop
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .Denied:
// if user denies access, display modal
self.performSegueWithIdentifier("NotifyModally", sender: self)
setUpMap() // need this func to execute AFTER location is selected
break
case .AuthorizedWhenInUse:
setUpMap()
break
default:
break
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "NotifyModally") {
let destViewController:ModalViewController = segue.destinationViewController as! ModalViewController
// send selectedStop var to ModalViewController
destViewController.selectedStop = selectedStop
}
}
}
模态ViewController.swift
class ModalViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var busStops = ["Stop 1", "Stop 2", "Stop 3"]
var selectedStop: Int!
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return busStops.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel!.text = busStops[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedStop = indexPath.row
dismissViewControllerAnimated(true, completion: nil)
}
}
使用 Int
变量传递信息将不起作用,因为它是 value 类型,每次传递它时都会被复制。因此,这意味着当您更改 didSelectRowAtIndexPath
方法中的 selectedStop
时, ViewController
中的原始 selectedStop
仍将是 nil 或其他任何内容。
然后,回答你的问题。有几种方法可以解决这个问题。
您可以像这样将 block
(而不是 int
)传递给 ModalViewController
:
var stopSelectedHandler: (Int) -> Void = { selectedStop in
// Do something here.
// setUpMap()
}
您将在 dismissViewControllerAnimated
的 completion
处理程序中调用此块。
您可以使用通知。
// Do this inside `ViewController`.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "setupMap:", name: "UserDidSelectStop", object: nil)
// And then post the notification inside `didSelectRowAtIndexPath`
NSNotificationCenter.defaultCenter().postNotificationName("UserDidSelectStop", object: nil, userInfo: ["selectedStop": 2])
// Change your setupMap to this
func setupMap(notification: NSNotification) {
guard let selectedStop = notification.userInfo?["selectedStop"] as? Int else { return }
// Now you can use selectedStop.
}
你也可以使用KVO、delegate等,用你喜欢的就可以了。
像这样放置积木:
class ViewController: UIViewController {
var stopSelectedHandler: (Int) -> Void = { selectedStop in
// Do something here.
// setUpMap()
}
....
}
我正在构建一个应用程序,如果用户不允许使用 模态呈现 的模式访问他们当前的位置,则要求用户select 一个位置一旦用户点击 'Deny'。此模态将信息显示为 TableView,一旦用户 select 一行,模态就会消失。我将这个 selection 保存在一个名为 selectedStop
的变量中。 我希望应用程序暂停,直到用户 select 找到一个位置,然后一旦用户 select 找到一个位置,应用程序就会继续并执行 setUpMap() 函数.我尝试在 setUpMap() 中使用无限 while
循环,并在用户 select 连续使用布尔值时立即跳出它,但是 while 循环甚至在 Modal 弹出之前执行.
ViewController.swift
class ViewController: UIViewController {
var selectedStop: Int!
override func viewDidLoad() {
super.viewDidLoad()
// If we don't have access to the user's current location, request for it
if (CLLocationManager.authorizationStatus() != CLAuthorizationStatus.AuthorizedWhenInUse) {
locationManager.requestWhenInUseAuthorization()
}
}
func setUpMap() {
// do stuff with var selectedStop
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .Denied:
// if user denies access, display modal
self.performSegueWithIdentifier("NotifyModally", sender: self)
setUpMap() // need this func to execute AFTER location is selected
break
case .AuthorizedWhenInUse:
setUpMap()
break
default:
break
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "NotifyModally") {
let destViewController:ModalViewController = segue.destinationViewController as! ModalViewController
// send selectedStop var to ModalViewController
destViewController.selectedStop = selectedStop
}
}
}
模态ViewController.swift
class ModalViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var busStops = ["Stop 1", "Stop 2", "Stop 3"]
var selectedStop: Int!
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return busStops.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel!.text = busStops[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedStop = indexPath.row
dismissViewControllerAnimated(true, completion: nil)
}
}
使用 Int
变量传递信息将不起作用,因为它是 value 类型,每次传递它时都会被复制。因此,这意味着当您更改 didSelectRowAtIndexPath
方法中的 selectedStop
时, ViewController
中的原始 selectedStop
仍将是 nil 或其他任何内容。
然后,回答你的问题。有几种方法可以解决这个问题。
您可以像这样将
block
(而不是int
)传递给ModalViewController
:var stopSelectedHandler: (Int) -> Void = { selectedStop in // Do something here. // setUpMap() }
您将在 dismissViewControllerAnimated
的 completion
处理程序中调用此块。
您可以使用通知。
// Do this inside `ViewController`. NSNotificationCenter.defaultCenter().addObserver(self, selector: "setupMap:", name: "UserDidSelectStop", object: nil) // And then post the notification inside `didSelectRowAtIndexPath` NSNotificationCenter.defaultCenter().postNotificationName("UserDidSelectStop", object: nil, userInfo: ["selectedStop": 2]) // Change your setupMap to this func setupMap(notification: NSNotification) { guard let selectedStop = notification.userInfo?["selectedStop"] as? Int else { return } // Now you can use selectedStop. }
你也可以使用KVO、delegate等,用你喜欢的就可以了。
像这样放置积木:
class ViewController: UIViewController {
var stopSelectedHandler: (Int) -> Void = { selectedStop in
// Do something here.
// setUpMap()
}
....
}