内存泄漏与NavigationController和多个UIViewController

时间:2018-02-16 10:05:17

标签: ios xamarin uiviewcontroller uinavigationcontroller

在我的应用程序中,我管理4个UIViewController:

  • 第一个用于处理用户登录的
  • 显示菜单的第二个
  • 第三个用于显示可用操作,具体取决于上一视图中的用户条目。
  • 第四个显示有关第三个视图中上一个选定项目的详细信息。

第三个和第四个显示带有要选择项的UIViewTable,它们被传递给下一个UIViewController以显示信息。

所以我注意不要互相使用硬链接。当UIViewControlle实例化时传递参数。

以下是我正在处理的问题: 当我从第三到第四,然后回到第四,记忆永远不会被释放。值得,当我回到第四时,它会再次占用相同数量的内存。

3-4次往返后,设备内存已满。 (UIImageView的另一个奇怪的行为是将12Mo的内存带到任何图片,无论图片大小是12Ko还是120Ko ......)

以下是用于在控制器之间切换的代码:

//First UIViewController, tagged as Root in storyboard
public partial class LoginController
{
    //....some logic code here


    //User ask for login by pressed a button , after an echange with a server 
    //for credential verification, if the server reply "ok" then I call the second
    //UIViewController like this

    void PushHomeScreen()
    {
        HomeController homeController = Storyboard.InstantiateViewController("home") as HomeController;
        NavigationController.PushViewController(homeController, false);
    }
}

public partial class HomeController
{
    //....some logic code here
    //The view displaying 3 UIButton that root to 2 different UIViewController.
    //First one is deadend, and user can only go back. It will be used one time to select a dataset to download and use after.
    //The two next use the same UIViewController, only the way that the controller handle the nexts user action is different :
    //If user came from the Second then it display screen for retrieving user attendance
    //If user came from the Third then it display screen for retrievin user survey.
    //So here are the code behind:
    private void BtnDownload_TouchUpInside(object sender, EventArgs e)
    {
        DownloadController downloadTrainingController = Storyboard.InstantiateViewController("downloadTraining") as DownloadController;
        NavigationController.PushViewController(downloadTrainingController, false);
    }

    private void BtnSurvey_TouchUpInside(object sender, EventArgs e)
    {
        TrainingAndReviewListController trakningController = Storyboard.InstantiateViewController("trakning") as TrainingAndReviewListController;
        trakningController.backgroundColor = "violet";
        NavigationController.PushViewController(trakningController, false);
    }

    private void BtnTraining_TouchUpInside(object sender, EventArgs e)
    {
        TrainingAndReviewListController trakningController = Storyboard.InstantiateViewController("trakning") as TrainingAndReviewListController;
        trakningController.backgroundColor = "red";
        NavigationController.PushViewController(trakningController, false);
    }
}

//I will not show you the DownloadController as it is not pertinent to the current probleme.


public partial class TrainingAndReviewListController
{
    //To handle the back action, so user go from this to HomeController
    void BtnHome_TouchUpInside(object sender, EventArgs e)
    {
        NavigationController.PopViewController(false);
    }

    private void Tablesource_OnRowSelected(object sender, DownloadTableSource.RowSelectedEventArgs e)
    {
        serviceController = Storyboard.InstantiateViewController("service") as ServiceController;   
        serviceController.backgroundColor = backgroundColor;
        serviceController.training = e.training;
        NavigationController.PushViewController(serviceController, false);
    }
}

//Next are the final UIViewController on the storyboard. It consume a lot of memory in inspector due to 20 UIViewImage on it who each consume 12Mo of memory.
//When I come back from this Controller to the previous memory are never released, and if I return on it, it consume the same amount extra again
//One solution to prevent this is to instanciate him once in TrainingAndReviewListController as class attribute, and then reuse it. But it is not supposed to be the role
//of the NavigationController?
public partial class ServiceController
{
    public string backgroundColor = "red";
    public Training training;

    //To handle the user action for going to the Home controller, this is not the action that cause memory leaks, altoutgh it will cause the same behavior I think.
    void BtnHome_TouchUpInside(object sender, EventArgs e)
    {
        foreach (UIViewController uiviewcontroller in NavigationController.ViewControllers) {
            if (uiviewcontroller.GetType() == typeof(HomeController)) {
                NavigationController.PopToViewController(uiviewcontroller as HomeController, false);
            }
        }
    }

    void BtnGoBack_TouchUpInside(object sender, EventArgs e)
    {
        Console.WriteLine(NavigationController.ViewControllers.Count()); //It always log the same count, as if the controller is really be poped when i come back and pop again.
        //But profilage show me that memory still used by this instance.
        NavigationController?.PopViewController(false);
    }
}

0 个答案:

没有答案