UIViewController
alt sınıfına sahibim, bu da UITableViewController
== HUDTableViewController
'u taklit eder. Sonra bu alt sınıf görüntü denetleyicisinden alt sınıfını (SomeViewController : HUDTableViewController
).UIViewController alt sınıfı (UITableViewController'ı taklit eder) yayınlanmadı
Bir bellek uyarısı taklit edersem SomeViewController
yayımlanamaz. İşte HUDTableViewController
ait kodudur:
using System;
using Foundation;
using UIKit;
namespace MyApp
{
public class HUDTableViewController : UIViewController, IUITableViewDataSource, IUITableViewDelegate, IDisposable, IUIScrollViewDelegate
{
private UIView parentView;
private UITableView tableView;
public UITableView TableView
{
get
{
return this.tableView;
}
set
{
this.tableView = value;
}
}
public HUDTableViewController() : base()
{
Initialize();
}
private void Initialize()
{
this.tableView = new UITableView();
this.tableView.TranslatesAutoresizingMaskIntoConstraints = false;
this.tableView.WeakDelegate = this;
this.tableView.WeakDataSource = this;
this.parentView = new UIView();
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.parentView.AddSubview(this.tableView);
View = this.parentView;
NSMutableDictionary viewsDictionary = new NSMutableDictionary();
viewsDictionary["parent"] = this.parentView;
viewsDictionary["tableView"] = this.tableView;
this.parentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[tableView]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
this.parentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[tableView]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
}
[Foundation.Export("numberOfSectionsInTableView:")]
public virtual System.nint NumberOfSections(UIKit.UITableView tableView)
{
return 1;
}
public virtual System.nint RowsInSection(UIKit.UITableView tableview, System.nint section)
{
throw new NotImplementedException();
}
public virtual UIKit.UITableViewCell GetCell(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
throw new NotImplementedException();
}
[Export("tableView:estimatedHeightForRowAtIndexPath:")]
public virtual System.nfloat EstimatedHeight(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
return UITableView.AutomaticDimension;
}
[Foundation.Export("tableView:didSelectRowAtIndexPath:")]
public virtual void RowSelected(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
}
[Export("tableView:heightForRowAtIndexPath:")]
public virtual System.nfloat GetHeightForRow(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
return 44.0f;
}
[Foundation.Export("tableView:heightForHeaderInSection:")]
public virtual System.nfloat GetHeightForHeader(UIKit.UITableView tableView, System.nint section)
{
return UITableView.AutomaticDimension;
}
[Foundation.Export("tableView:viewForHeaderInSection:")]
public virtual UIKit.UIView GetViewForHeader(UIKit.UITableView tableView, System.nint section)
{
return null;
}
[Export("tableView:titleForHeaderInSection:")]
public virtual string TitleForHeader(UITableView tableView, nint section)
{
return string.Empty;
}
[Foundation.Export("tableView:willDisplayCell:forRowAtIndexPath:")]
public virtual void WillDisplay(UIKit.UITableView tableView, UIKit.UITableViewCell cell, Foundation.NSIndexPath indexPath)
{
}
}
}
tableView
referans 2 sayısı gösterilir (çünkü AddSubView
ve benim mal) olması gerekir. SomeEventHandler
arasında, çünkü SomeViewController
MasterViewContainer
bir referans yer alır görüldüğü gibi
public class MasterViewContainer : UIViewController
{
private bool hasSetupHandlersAndEvents = false;
// ...
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
if (!hasSetupHandlersAndEvents) {
if (listButton != null) {
listButton.Clicked += listButton_Clicked;
}
hasSetupHandlersAndEvents = true;
}
}
public override void ViewWillDisappear (bool animated)
{
base.ViewWillDisappear (animated);
if (hasSetupHandlersAndEvents) {
if (listButton != null) {
listButton.Clicked -= listButton_Clicked;
}
hasSetupHandlersAndEvents = false;
}
}
private void listButton_Clicked(object sender, EventArgs args){
SomeViewController viewController = new SomeViewController();
viewController.SomeEvent += SomeEventHandler;
NavigationController.PushViewController(viewController, false);
}
}
:
Bu SomeViewController
başlatır ana görünümü kontrol cihazıdır. Ben
public class SomeViewController : UITableViewController
kullanırsanız
SomeViewController
serbest bırakılır ama
public class SomeViewController : HUDTableViewController
Dispose
yöntemi asla denir kullanırsak serbest bırakılmaz. Bir referans döngüsü görmüyorum. Bir şeyi nasıl bırakmak zorundayım? Neyi özlüyorum?
1 deneyin:
Bu aklıma gelen tek çözümdür. Referansı SomeViewController
tuttuğum bir alan (sınıf değişkeni) kullanıyorum. DidReceiveMemoryWarning
'da manuel olarak serbest bırakıyorum/atın. Alana erişmek istediğimde, daha önce başlatılmış olup olmadığını kontrol ediyorum. Gerekmiyorsa, gerektiğinde başlatabilirim.
public class MasterViewContainer : UIViewController
{
private SomeViewController viewController;
public override void DidReceiveMemoryWarning()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
if (this.viewController != null)
{
this.viewController.SomeEvent -= SomeEventHandler;
this.viewController.Dispose();
this.viewController = null;
}
}
private void listButton_Clicked(object sender, EventArgs args){
if (this.viewController == null)
{
this.viewController = new SomeViewController();
this.viewController.SomeEvent += SomeEventHandler;
}
NavigationController.PushViewController(this.viewController, false);
}
Ancak bu çözüm mükemmel değildir. Dispose, görünüm şu anda ekranda görüntülendiğinde de çağrılır. Bu yüzden arızaların olması çok muhtemeldir.
Bounty: Ben bellek yönetim sorunu açıklayan bir çözüm olmasını istiyorum
. Neden serbest bırakılmıyor? Serbest bırakmak için ne değişmeli (denemem gibi şeyler yapmadan). UITableViewController
gibi davranmalıdır.
2 deneyin:
Şimdi Dispose(bool disposing)
HUDTableViewController
ait geçersiz kılmak için çalıştı: Ne HUDTableViewController
bu Dispose
yöntem ne de SomeViewController
ait Dispose
yöntem
protected override void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
this.tableView.RemoveFromSuperview();
this.tableView.Dispose();
}
this.disposed = true;
}
base.Dispose(disposing);
}
denir.
Bunun için ne gerekir? ViewDidLoad'da oluşturulacağı garanti edilen denetleyici için zaten bir kök görünümü var. Bu nedenle, tablonun alt görünümü olarak tableView eklemek yerine, * parentview'ınızla * değiştirin. Orijinal görünüm, hiyerarşide devam edebilir ve denetleyiciye başvuruda bulunabilir, böylece ikincisi serbest bırakılmaz. –
Bu 'HUDTableViewController' kullanıyorum çünkü üzerinde bir yükleme döndürücü merkezlemek istiyorum. Bu yüzden daha fazla çaba harcamadan bu sınıfı kullanabilirim. Merkezleme için, 'ViewView' ('UITableView' olan) çalışmıyor ve 'UITableView'ün ebeveyini kullanmayı denedim. Referansı bir şekilde serbest bırakan bazı seçenekler var mı? Ya da belki de bir 'UITableView' içinde bir görüntüyü merkezileştiren daha iyi bir fikriniz var. – testing
Dispose() yöntemini açık bir şekilde uygulamanız gerekmiyor mu? –