ios - 呈现新 View Controller 时销毁以前的 View Controller

标签 ios swift protocols delegation presentviewcontroller

我有一个带有 sideBarMenu 的应用程序,它有五个部分。在我的 Storyboard 中,我创建了嵌入 NavigationController 的启动 MainViewController。然后我创建了相同的五个 VC,并再次将它们嵌入到 NavigationController 中。所以我有 6 个 VC,每个都包装在自己的 NavigationController 中。

每个 VC 都使用具有所选菜单索引的函数实现 sideBarDelegate。

代码如下:

// SideBarTableViewController

protocol SideBarTableViewControllerDelegate {
    func SideBarControlDidSelectRow(indexPath: NSIndexPath)
}

class SideBarTableViewController: UITableViewController {

// ...

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: false)
        println(indexPath.row)
        delegate?.SideBarControlDidSelectRow(indexPath)
    }
}


// SideBar class ------------------------------------------------

@objc protocol SideBarDelegate {
    func SideBarDidSelectButtonAtIndex(index: Int)
    optional func SideBarWillClose()
    optional func SideBarWillOpen()
}

class SideBar: NSObject, SideBarTableViewControllerDelegate {

// ...

    func SideBarControlDidSelectRow(indexPath: NSIndexPath) {
        println(indexPath.row)
        delegate!.SideBarDidSelectButtonAtIndex(indexPath.row)
    }
}

然后在这个函数中我想呈现所需的 ViewController:

func SideBarDidSelectButtonAtIndex(index: Int) {
    presentViewControllerByIndex(index)
}

func presentViewControllerByIndex(index: Int) {
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    switch index {
    case 0:
        var viewController = storyBoard.instantiateViewControllerWithIdentifier("SearchVC") as! SearchViewController
        viewController.delegate = self
        self.presentViewController(viewController, animated: false, completion: nil)
        break

    // the same code here for other 4 VC's with their StoryboardId's

    default: break
    } 
}

然后在呈现的 View Controller 中,如果用户在菜单中选择另一个部分,我应该在呈现选定的 ViewController 之前销毁此 VC 吗?因为当我运行我的应用程序并开始在 Controller 之间切换时,xCode 中的应用程序内存会增加(screenshot)。

当我看到我开始谷歌搜索并找到 this 时回答。所以我在我的第一个菜单 VC 中创建了一个协议(protocol),只是为了测试。

protocol myProtocol {
    func dissmissAndPresend(index: Int) -> Void
}

当我需要展示新的 VC 时,我只需调用:

self.delegate?.dissmissAndPresend(index)

然后在我的 MainVC 中,我实现了这个协议(protocol)并尝试关闭以前的 VC 并呈现新的:

class MainViewController: UIViewController, SideBarDelegate, myProtocol {

func dissmissAndPresend(index: Int) {
    self.dismissViewControllerAnimated(false, completion: {
        self.presentViewControllerByIndex(index)
    })
}

现在,当我启动我的程序并开始单击第一个菜单项时,它会打开新的 VC,但我的内存会像以前一样增加。呈现 View 的 navigationController 也不见了,但在 Storyboard中呈现的 VC 嵌入在 navigationController 中。

我做错了什么?有人可以帮助我吗?

更新::--------------------------------

这是我尝试过的:

class MainViewController: UIViewController, SideBarDelegate, searchVCProtocol {
    var searchVC: SearchViewController!
    var searchNavController: ShadowUINavigationController!

    override func viewDidLoad() {
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        searchVC = mainStoryboard.instantiateViewControllerWithIdentifier("SearchVC") as! SearchViewController
        searchVC.delegate = self
        searchNavController = ShadowUINavigationController(rootViewController: searchVC)
    }

    func SideBarDidSelectButtonAtIndex(index: Int) {
        switch index {
        case 0:
            println("asda")
            self.presentViewController(searchNavController, animated: false, completion: nil)
            break
        }
    }

然后它将用户带到 SearchViewController,如果用户再次打开菜单并再次单击 SearchViewController 会怎样。我怎样才能关闭它并重新打开。这是我尝试过但不起作用的方法:

在 SeachViewController 中我创建了一个协议(protocol):

protocol searchVCProtocol {
    func dismissAndPresent(index: Int) -> Void
}

然后我为委托(delegate)添加了一个变量:

var delegate: searchVCProtocol?

然后当用户选择菜单项时它会触发此事件:

func SideBarDidSelectButtonAtIndex(index: Int) {
    delegate?.dismissAndPresent(index)
}

在 MainViewController 中,我实现了这个协议(protocol)并创建了 dismissAndPresent 方法,但我不知道如何重新启动呈现的 viewController。

class MainViewController: UIViewController, SideBarDelegate, searchVCProtocol {
    func dismissAndPresent(index: Int) {
        // code to restart this VC
    }
}

我应该编写什么代码来重启呈现的 VC?

最佳答案

您每次都在调用 instantiateViewControllerWithIdentifier,每次都会创建(“实例化”)一个新的 ViewController。最好只执行一次,保留对它的引用,然后根据需要重新使用它。

在这里你可以如何保持引用。首先,您在类级别创建一个新变量:

class MyClass {
    var viewController: SearchViewController!

然后,在 viewDidLoad 中,实例化 View Controller 并将其分配给变量。

func viewDidLoad() {
    viewController = storyBoard.instantiateViewControllerWithIdentifier("SearchVC") as! SearchViewController
}

viewDidLoad 只被调用一次,因此您不会再创建多个实例。

然后你可以一次又一次地重用这个 View Controller :

func presentViewControllerByIndex(index: Int) {
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    switch index {
    case 0:
        // Here you can reuse the formerly created viewcontroller 
        viewController.delegate = self
        self.presentViewController(viewController, animated: false, completion: nil)
        break

    // the same code here for other 4 VC's with their StoryboardId's

    default: break
    } 
}

关于ios - 呈现新 View Controller 时销毁以前的 View Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31783168/

相关文章:

ios - 使用核心数据中的 NSFetchRequest 来获取聚合关系计数?

ios - Swift - App store reject - 部分应用转发器以重新抽象 thunk helper

ios - Swift:在解雇的完成处理程序中呈现 VC

ios - CollectionView 延迟选择

ios - 从 CoreData 模块获取数据

ios - UISearchController 仅在单击搜索按钮时更新

ios - 核心数据中反向对多关系的数据库设计

protocols - 要文件的 Protocol Buffer ?

Redis批量插入: protocol vs inline commands

file - 如何拦截文件 ://requests to provide a directory listing?