在执行代码之前等待用户关闭模态视图 (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 或其他任何内容。

然后,回答你的问题。有几种方法可以解决这个问题。

  1. 您可以像这样将 block(而不是 int)传递给 ModalViewController

    var stopSelectedHandler: (Int) -> Void = { selectedStop in
        // Do something here.
        // setUpMap()
    }
    

您将在 dismissViewControllerAnimatedcompletion 处理程序中调用此块。

  1. 您可以使用通知。

    // 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()
    }
    ....
}