我想向人们保证,当使用按钮从堆栈中弹出控制器时,我通过互联网解释了内存泄漏的所有文章,并且我知道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吗?
答案 0 :(得分:1)
修改这部分代码对我有用。
Servlet 3
//下面的修改与问题陈述无关,但由于按钮不需要为空而需要
private void HandleBackClick(object sender, EventArgs e)
{
tableView.Delegate = null;
tableView.DataSource = null;
tableView.Source = null;
this.NavigationController.PopViewController(true);
}