从Xamarin.iOS中的导航堆栈弹出后,ViewController没有被释放

时间:2017-05-14 14:04:16

标签: ios xamarin xamarin.ios mono

我想向人们保证,当使用按钮从堆栈中弹出控制器时,我通过互联网解释了内存泄漏的所有文章,并且我知道UIButton在使用Lambdas触发事件时创建的强引用。

我曾尝试过所有似乎都不适合我的人。

问题陈述

我有一个UICollectionViewController作为Root ViewController,它上面有一个浮动按钮,我以编程方式创建并添加为子视图。

这些按钮将viewcontrollers推入堆栈。

这是推动控制器的方法。

private void HandleClick(object sender, EventArgs e) {

    var button = sender as UIButton;
    var board = UIStoryboard.FromName("Main", NSBundle.MainBundle);
    switch (button.Tag) { 

        case 3: { 
                var vc = board.InstantiateViewController("BibleViewController");
                this.NavigationController.PushViewController(vc, true);
                vc = null;

                break;

            }
        case 5: { 
                var vc = board.InstantiateViewController("RecordingViewController");
                this.NavigationController.PushViewController(vc, true);
                vc = null;

                break;
            }
        case 7: {  
                var vc = board.InstantiateViewController("CameraFbController");
                this.NavigationController.PushViewController(vc, true);
                vc = null;

                break;
            }
        case 6: {
                var vc = board.InstantiateViewController("NewEmojiController");
                this.NavigationController.PushViewController(vc, true);
                vc = null;

                break;
            }
        case 4: { 
                var vc = board.InstantiateViewController("WriteNShareController");
                this.NavigationController.PushViewController(vc, true);
                vc = null;
                break;
            }
        default : {
                break;
            }



    }
}

假设我正在推送BibleViewController(案例3 :)

请找到此控制器的代码

public partial class BibleHomeController : UIViewController
{
    IList<string> items;
    IList<string> item1;

    public BibleHomeController() : base("BibleHomeController", null)
    {
    }
    public BibleHomeController(IntPtr handle) : base (handle)
    {
    }
    ~BibleHomeController() { 

        Console.WriteLine("it was called ");

    }
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        LoadJson();

        tableView.DataSource = new BTableViewDataSource(items);
        tableView.Delegate = new TableDelegate(items,this);
        tableView.RegisterNibForCellReuse(UINib.FromName("BookCell",NSBundle.MainBundle),BookCell.Key);




    }
    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        backBtn.TouchUpInside += HandleBackClick;
        nwBtn.TouchUpInside += newBtn;
        oldBtn.TouchUpInside += oldBtnHanle;
    }
    private void HandleBackClick(object sender, EventArgs e)
    {

        this.NavigationController.PopViewController(true);
    }
    public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);
        backBtn.TouchUpInside -= HandleBackClick;
        nwBtn.TouchUpInside -= newBtn;
        oldBtn.TouchUpInside -= oldBtnHanle;
                    backBtn = null;
        nwBtn = null;
        oldBtn = null;
        tableView = null;

    }
    private void newBtn(object sender, EventArgs e)
    {

        tableView.DataSource = new BTableViewDataSource(item1);
        tableView.Delegate = new TableDelegate(item1,this);
        tableView.ReloadData();
    }
    private void oldBtnHanle(object sender, EventArgs e)
    {

        tableView.DataSource = new BTableViewDataSource(items);
        tableView.Delegate = new TableDelegate(items,this);
        tableView.ReloadData();
    }
    public override void DidReceiveMemoryWarning()
    {
        base.DidReceiveMemoryWarning();
        // Release any cached data, images, etc that aren't in use.
    }
    private void LoadJson() {
        using (StreamReader r = new StreamReader("BibleSection/BibleBooks/Books.json")) {
            string json = r.ReadToEnd();
            items = JsonConvert.DeserializeObject<List<string>>(json);
        }
        using (StreamReader r = new StreamReader("BibleSection/BibleBooks/NewBook.json"))
        {
            string json = r.ReadToEnd();
            item1 = JsonConvert.DeserializeObject<List<string>>(json);
        }
    }

}
public class BTableViewDataSource : UITableViewDataSource
{
    IList<string> data;

    public BTableViewDataSource(IList<string> list) {

        data = list;
    }
    ~BTableViewDataSource() {
        Console.WriteLine("it was called ");
    }
    public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
    {
        // if cell is not available in reuse pool, iOS will create one automatically
        // no need to do null check and create cell manually
        var cell = (BookCell)tableView.DequeueReusableCell("BookCell", indexPath) as BookCell;
        cell.PopulateCell(data[indexPath.Row], "");
        cell.SetNeedsLayout();

        //cell.SeparatorInset = UIEdgeInsets.Zero;
            return cell;

    }

    public override nint RowsInSection(UITableView tableView, nint section)
    {

        return data.Count;

    }


}
public class TableDelegate : UITableViewDelegate { 
    IList<string> data;
    BibleHomeController owner;
    public TableDelegate(IList<string> list, BibleHomeController reference)
    {
        owner = reference;
        data = list;
    }
    ~TableDelegate()
    {
    Console.WriteLine("it was called ");
    }
    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
    {
        //base.RowSelected(tableView, indexPath);
        var board = UIStoryboard.FromName("Main", NSBundle.MainBundle);
        var vc = (BibleChapterCollectionview)board.InstantiateViewController("BibleChapterCollectionview") as BibleChapterCollectionview;
        vc.itemName = data[indexPath.Row];
        owner.NavigationController.PushViewController(vc, true);

    }

}

我的问题是,当我在BibleViewController中弹出控制器时, 没有类的析构函数被调用既不调用dispose也不调用控制器内存。

所以每当我推送和弹出时,我都会添加一些内存来堆。

我想指出,我是在viewDidDisappear方法中从按钮中分离所有事件处理程序。

当你弹出控制器时,能帮我解释如何释放资源。

编辑: 我认为问题在于tableview.delegate和table.datasource行。 如果我评论他们问题就解决了。

我应该使用weakDelegate吗?

1 个答案:

答案 0 :(得分:1)

修改这部分代码对我有用。

Servlet 3

//下面的修改与问题陈述无关,但由于按钮不需要为空而需要

private void HandleBackClick(object sender, EventArgs e)
    {
            tableView.Delegate = null;
            tableView.DataSource = null;
            tableView.Source = null;
        this.NavigationController.PopViewController(true);
    }