2016-12-19 62 views
1

在我的应用程序中,使用Xamarin Profiler,我注意到无论何时将VC推入堆栈并导航回内存分配都不是免费的。如果我再次推动相同的视图,它会增加更多的内存。向后导航不会释放内存

我创建了一个示例项目来测试,我发现这是做同样的事情。

示例项目:

我有两个视图控制器,VC1和VC2。 VC1是根视图控制器。

每当我从VC1推VC2时,都会分配内存,但是当我导航回时,内存不是免费的。如果我继续推VC2,它会增加更多内存。在VC2中,我通过设计师添加了3个标签。

中的AppDelegate:

namespace TestSample 
{ 
    [Register("AppDelegate")] 
    public class AppDelegate : UIApplicationDelegate 
    { 
     public override UIWindow Window 
     { 
      get; 
      set; 
     } 

     public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) 
     { 
      Window = new UIWindow(UIScreen.MainScreen.Bounds); 
      var nav = new UINavigationController(new MyViewController()); 
      Window.RootViewController = nav; 
      Window.MakeKeyAndVisible(); 

      return true; 
     } 
    } 
} 

VC1:

namespace TestSample 
{ 
    public partial class MyViewController : UIViewController 
    { 
     public MyViewController() : base("MyViewController", null) 
     { 
     } 

     public override void ViewDidLoad() 
     { 
      base.ViewDidLoad(); 
      // Perform any additional setup after loading the view, typically from a nib. 
     } 
     public override void ViewWillAppear(bool animated) 
     { 
      base.ViewWillAppear(animated); 

      btn1.TouchUpInside += Btn1_TouchUpInside; 
     } 

     void Btn1_TouchUpInside(object sender, EventArgs e) 
     { 
      NavigationController.PushViewController(new MyViewController2(), true); 
     } 

     public override void ViewDidDisappear(bool animated) 
     { 
      base.ViewDidDisappear(animated); 
      btn1.TouchUpInside -= Btn1_TouchUpInside; 
     } 

     public override void DidReceiveMemoryWarning() 
     { 
      base.DidReceiveMemoryWarning(); 
      // Release any cached data, images, etc that aren't in use. 
     } 
    } 
} 

VC2:在Xamarin.iOS

namespace TestSample 
{ 
    public partial class MyViewController2 : UIViewController 
    { 
     public MyViewController2() : base("MyViewController2", null) 
     { 
     } 

     public override void ViewDidLoad() 
     { 
      base.ViewDidLoad(); 
      // Perform any additional setup after loading the view, typically from a nib. 
     } 

     public override void DidReceiveMemoryWarning() 
     { 
      base.DidReceiveMemoryWarning(); 
      // Release any cached data, images, etc that aren't in use. 
     } 

     public override void ViewDidDisappear(bool animated) 
     { 
      base.ViewDidDisappear(animated); 
      /*foreach (UIView view in View.Subviews) { 
       view.RemoveFromSuperview(); 
      }*/ 

      label1.RemoveFromSuperview(); 
      label2.RemoveFromSuperview(); 
      label3.RemoveFromSuperview(); 

      label1.Dispose(); 
      label2.Dispose(); 
      label3.Dispose(); 
     } 
    } 
} 
+0

你可以发布你的VC2吗?这里有一个循环引用,需要通过设置null或调用Dispose()来切断关系,否则GC将永远看不到有资格收集的对象。 –

+0

VC2只有3个标签,我通过设计者在XIB文件中添加了这些标签。编辑VC2 – PLOW

+0

@PLOW如果强制使用'GC.Collect()',回收内存? – SushiHangover

回答

5

垃圾收集完全不破。这是一种普遍的误解(在任何系统上),拥有GC意味着不必担心注意内存消耗和(强)参考。

X.iOS位于参考计数世界之上,这需要进行特定的测量。所有这些都被记录在案;是的,它可能很难理解所有的细微差别。

这就是说:我试过你的例子,VC2按预期方式收集(终结者和Dispose()被称为)。 Profiler(1.0.2-2)也不显示任何泄漏。

我创建了两个基于XIB的控制器,并向第一个和第三个标签添加了一个按钮。您不必删除或处理任何标签,也不必在案例中的第一个VC中取消订阅点击事件。

如果你的项目行为不同,你会在某处保留对VC2的引用。也许你可以提供完整的项目,然后我可以看看它。