0

以下に示すように、入れ子になった UITableViewSource クラスの新しいインスタンスに .Source プロパティを設定して、MonoTouch (Xamarin.iOS) で UITableView を作成するパターンに従います。別の開発者が注意を喚起した懸念は、ネストされたクラスのコンストラクターで割り当てられた _parentController プロパティを介してネストされたクラスが親クラスを参照するため、この UITableView クラスがガベージ コレクションを取得しないことです。ネストされたクラスがこの参照を保持している限り、親クラスは収集できないと考えられています。

これが本当かどうか、ガベージ コレクションがリソースを解放できないため、この方法で UITableView を作成することは良いプログラミング手法ではないことを誰でも確認できますか? (簡潔にするために一部のメソッドとコンストラクターは省略されています。

public partial class MyViewController : UITableViewController
{
   public override ViewDidLoad()
   {
      base.ViewDidLoad();
      this.TableView.Source = new ViewSource(this);
   }

   public class ViewSource : UITableViewSource
   {
      MyViewController _parentController;
      public ViewSource(MyViewController parentController)
      {
         _parentController = parentController;
      }
   }
}
4

1 に答える 1

4

発売されます。

その理由は、"Source" プロパティが Objective-C の弱いプロパティであるためです。つまり、その割り当てはオブジェクトの保持を呼び出さず、参照を保持するだけです。

GC の発生を妨げる強力なサイクルは、Objective-C 呼び出しが渡されたオブジェクトで保持されている場合にのみ発生します。

次の例は、データが最終的にどのようにリリースされるかを示しています。最初に何度もドリルダウンしてから、ドリルアップする必要があります。

public class MyViewController : UITableViewController {
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        this.TableView.Source = new ViewSource(this);
    }

    public class ViewSource : UITableViewSource
    {
        public override int RowsInSection (UITableView tableview, int section)
        {
            return 100;
        }

        public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
        {
            return new UITableViewCell (UITableViewCellStyle.Default, "foo");
        }

        public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
        {
            var n = AppDelegate.window.RootViewController as UINavigationController;
            n.PushViewController (new MyViewController (), true);
            GC.Collect ();
        }
        MyViewController _parentController;
        public ViewSource(MyViewController parentController)
        {
            _parentController = parentController;
        }
    }
    ~MyViewController ()
    {
        Console.WriteLine ("Disposing");
    }
}

[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
    public static UIWindow window;
    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        window = new UIWindow (UIScreen.MainScreen.Bounds);

        var myViewController = new MyViewController ();
        window.RootViewController = new UINavigationController (myViewController);
        window.MakeKeyAndVisible ();
        return true;
    }
}
于 2013-08-15T20:50:22.587 に答える