关闭模式视图但保留数据

Posted

技术标签:

【中文标题】关闭模式视图但保留数据【英文标题】:Dismissing a modal view but keeping the data 【发布时间】:2017-02-13 21:41:13 【问题描述】:

我试图关闭模态视图并返回到“发送”自的视图控制器,同时保留在模态视图中输入的数据。如果我理解正确,我需要为此使用委托/协议,但我很难理解如何在这种情况下实际实现它。

基本上用户可以调用模态视图在文本字段中输入一些信息,当他们点击保存时,这个函数被调用:

func handleSave() 

    guard let newProductUrl = NSURL(string: urlTextField.text!) else 
        print("error getting text from product url field")
        return
    
    guard let newProductName = self.nameTextField.text else 
        print("error getting text from product name field")
        return
    
    guard let newProductImage = self.logoTextField.text else 
        print("error getting text from product logo field")
        return
    

    // Call save function in view controller to save new product to core data
    self.productController?.save(name: newProductName, url: newProductUrl as URL, image: newProductImage)


    // Present reloaded view controller with new product added
    let cc = UINavigationController()
    let pController = ProductController()
    productController = pController
    cc.viewControllers = [pController]
    present(cc, animated: true, completion: nil)

它调用self.productController?.save 函数将新输入的值保存到核心数据中,并使用新产品重新加载productController 表视图。

但是我遇到的问题是 productController 表视图是根据其他一些因素动态设置的,所以我只想在用户输入数据后关闭模式视图,然后返回调用模态视图的页面。

编辑:尝试了解如何实现委托 -

ProductController 是用户访问模态视图的父类:

protocol ProductControllerDelegate: class 
func getData(sender: ProductController)



class ProductController: UITableViewController, NSFetchedResultsControllerDelegate, WKNavigationDelegate 

override func viewDidLoad() 
    super.viewDidLoad()

    weak var delegate:ProductControllerDelegate?



    func getData(sender: ProductController) 


AddProductController 是模态呈现的控制器,用户在其中输入数据,然后调用 handleSave,我想关闭并返回调用它的 ProductController 表视图:

class AddProductController: UIViewController, ProductControllerDelegate 

override func viewDidDisappear(_ animated: Bool) 
    // error on this line
    getData(sender: productController)

【问题讨论】:

【参考方案1】:

如果您的协议的唯一目的是返回视图控制器的最终状态,则使用展开转场而不是协议通常更容易和更清晰。

步骤:

1) 在父 VC 中创建一个 @IBAction unwind(segue: UIStoryboardSegue) 方法

2) 在呈现的 ViewController 的情节提要中,您可以控制从要触发退出的控件或黄色视图控制器本身(如果在代码中执行 segue)拖动到橙色退出图标。

您的代码应如下所示:

    @IBAction func unwind(segue: UIStoryboardSegue) 
        if let source = segue.source as? MyModalViewController  
            mydata = source.data
            source.dismiss(animated: true, completion: nil)
        
    

see apple documentation

这里的编辑是在没有情节提要的情况下触发和放松代码的黑客方式;我不赞成这样做:

        guard let navigationController = navigationController,
            let presenter = navigationController.viewControllers[navigationController.viewControllers.count - 2] as? MyParentViewController else 
            return
        
        presenter.unwind(UIStoryboardSegue(identifier: String(describing: self), source: self, destination: presenter))

【讨论】:

这是唯一的目的,所以我现在会尝试这种方式而不是委托,出于某种原因,我发现委托对于这样看似简单的任务真的很困惑..我是虽然不使用情节提要,但这都是程序化的。 您只能使用情节提要来做到这一点。否则你必须使用hackery。也就是说,您要么需要对视图控制器的引用,要么从导航控制器中获取它。见代码编辑 我认为它在 Swift 3 中可能有点不同,当我尝试骇客方法时,它需要一个 towardsViewController 参数。我试图将您的代码插入到正确的语法中,例如presenter.unwind(for: UIStoryboardSegue(identifier: String(describing: self), source: self, destination: presenter), towardsViewController: presenter),但遇到了崩溃【参考方案2】:

基本上,您需要在此模式视图中创建一个委托。 假设您有 ParentViewController 来创建这个模态视图控制器。 ParentViewController 必须实现委托方法,比如retrieveData(someData)。

在模态视图控制器上,您可以使用方法viewWillDisappear()来触发您要传递给父级的数据的委托方法:

delegate.retrieveData(someData)

如果您在理解如何实现委托时遇到问题,可以查看this link

【讨论】:

谢谢 Joan 我现在正在尝试 - 我应该在父视图控制器 (ProductController) 或模态控制器 (AddProductController) 中创建协议? 我想将handleSave中收集的数据传递给父级(ProductController),我可以传递整个函数吗?我的印象是handleSave 将用户输入的数据传递到核心数据中,然后 ProductController 正在从核心数据中读取 @d0xi45 您必须在 AddProductController 中声明协议,但在 ProductController 中实现它,请查看我之前发布的链接。我不知道你说的传递整个函数是什么意思,它的工作方式与调用任何其他函数一样。

以上是关于关闭模式视图但保留数据的主要内容,如果未能解决你的问题,请参考以下文章

lumen 开启调试模式,关闭debug输出,只保留数据验证提示

保存、保留和检索数组中的选定单元格

具有自定义委托或数据源的视图控制器的状态保留

iOS - 在其顶部呈现模式后保留视图控制器状态

补充与预告 切换页面时保留状态 后 增加 Tabs 模式 , 允许看到多个页面与关闭.

在 Blade 视图中保留前导零