在执行代码之前等待用户关闭模态视图(Swift 2.0)

Posted

技术标签:

【中文标题】在执行代码之前等待用户关闭模态视图(Swift 2.0)【英文标题】:Wait for user to dismiss Modal View before executing code (Swift 2.0) 【发布时间】:2016-03-10 22:27:43 【问题描述】:

我正在构建一个应用程序,如果用户在用户点击“拒绝”后立即使用以模式显示的模式访问其当前位置,他们会要求用户选择一个位置。此模式将信息显示为 TableView,一旦用户选择一行,模式就会消失。我将此选择保存在一个名为selectedStop 的变量中。 我希望应用暂停,直到用户选择一个位置,然后一旦用户选择一个位置,应用就会继续并执行 setUpMap() 函数。我尝试在 setUpMap() 中使用无限 while 循环,并在用户选择一行后立即使用布尔值打破它,但 while 循环甚至在模态弹出之前执行。

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
        
    

ModalViewController.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)
    

【问题讨论】:

【参考方案1】:

使用Int 变量传递信息将不起作用,因为它是一个 类型,每次传递时都会被复制。这意味着当您更改 didSelectRowAtIndexPath 方法中的 selectedStop 时,ViewController 中的原始 selectedStop 仍将为 nil 或其他任何内容。

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

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

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

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

    您可以使用通知。

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

【讨论】:

感谢您的帮助。如何将 block 传递给 MVC?我要destViewController.selectedStop = stopSelectedHandler吗? @Ivan 是的,您还必须在 destViewController 中声明一个块变量。 var stopSelectedHandler: ((Int) -> Void)?destViewController.stopSelectedHandler = stopSelectedHandler 我应该把var stopSelectedHandler: (Int) -> Void = selectedStop in ... 放在哪里?那是在destViewController.selectedStop = stopSelectedHandler 之前吗?我为造成的混乱道歉,我还在学习 Swift。 @Ivan 可以放在前面。您还可以将块视为属性。检查我的答案。

以上是关于在执行代码之前等待用户关闭模态视图(Swift 2.0)的主要内容,如果未能解决你的问题,请参考以下文章

使用 swift 在选项卡式应用程序中模态显示和关闭视图

我该如何做模态对话框片段(代码在我关闭之前不会执行)

在 Swift 中显示和关闭模态视图控制器

当模态视图(第二个视图)被关闭时刷新 ViewController 中的核心数据 - Swift

swift 关闭模态视图

Tkinter:等待用户点击