2011-03-01 32 views
0

参照这个页面控制的例子可能有人请解释代码流?乐器在这里给我泄漏,所以寻找一些帮助。可能在这个例子中解释代码流?内存泄漏?哪里?

回复:本教程: http://www.edumobile.org/iphone/iphone-programming-tutorials/pagecontrol-example-in-iphone/

我们初始化数组为NULL我们AppDidFinishLaunching方法的对象......

NSMutableArray *controllers = [[NSMutableArray alloc] init]; 
for (unsigned i = 0; i < kNumberOfPages; i++) { 
    [controllers addObject:[NSNull null]]; 
} 
self.viewControllers = controllers; 
[controllers release]; 

,然后调用:

[self loadScrollViewWithPage:0]; 
[self loadScrollViewWithPage:1]; 

这里是实施loadScrollViewWithPage

- (void)loadScrollViewWithPage:(int)page { 
if (page < 0) return; 
if (page >= kNumberOfPages) return; 

PageControlExampleViewControl *controller = [viewControllers objectAtIndex:page]; 
if ((NSNull *)controller == [NSNull null]) { 
    controller = [[PageControlExampleViewControl alloc] initWithPageNumber:page]; 
    [viewControllers replaceObjectAtIndex:page withObject:controller]; 
    [controller release]; 
} 

if (nil == controller.view.superview) { 
    CGRect frame = scrollView.frame; 
    frame.origin.x = frame.size.width * page; 
    frame.origin.y = 0; 
    controller.view.frame = frame; 
    [scrollView addSubview:controller.view]; 
} 
} 

仪器是给我一个泄漏以下行此实现:

如果(零== controller.view.superview){

任何人都知道为什么,这将是一个报道仪器泄漏?我的代码是相同的。 也在初始调用后[self loadScrollViewWithPage:0];,第一次通过并创建对象,BOTH如果条款已通过并进入。

这怎么可能? 如果我们输入第一个如果条款,我们分配并创建我们的控制器,并通过**释放*它([控制器发布])结束。

应该不是下一行(如果(零== controller.view.superview))生产,因为我们刚刚发布了上述控制器的EXC_BAD_ACCESS错误看见了什么?

屏幕截图FROM INSTRUMENTS: Instruments screenshot

回答

1

我不知道为什么仪器会报告该行的泄漏,除非它只是注意到controller.view是由该行分配的(访问UIViewController的视图属性会自动加载视图,如果有必要)还没有被释放(它不应该像scrollView一样存在,controller.view仍然是子视图)。

这是正确的,它通过if条款。第一个if检查该页面索引是否实际存在视图控制器,如果不存在,则创建一个(但不会将其添加到scrollView)。第二个检查页面索引的视图控制器的视图是否已经添加到scrollView,如果没有,则添加它。

它不会崩溃的原因是因为[viewControllers replaceObjectAtIndex:page withObject:controller]将控制器添加到保留控制器的NSMutableArray。它可能会略有减少混乱,像这样做,而不是:

if ((NSNull *)controller == [NSNull null]) { 
    controller = [[[PageControlExampleViewControl alloc] initWithPageNumber:page] autorelease]; 
    [viewControllers replaceObjectAtIndex:page withObject:controller]; 
} 
+0

为受影响的行添加了乐器输出的屏幕截图。就像你说的那样,我真的不知道为什么这会漏水。在它正在泄漏的线虽然_controller.view_是**不是**滚动视图的子视图呢?它将它添加到它即将进入的子句中? – 2011-03-01 18:38:34

+0

从你的截图中,它抱怨分配的视图。报告泄漏的行是分配视图之前程序中的最后一行。你在某个时候漏了scrollView吗?这可能会导致Instruments将其所有子视图计数为泄漏。 – Anomie 2011-03-01 19:12:15

0

在我看来,你是不是正确地释放滚动视图。

0

这怎么可能?如果我们输入第一个if子句,我们分配并创建我们的控制器,并以*释放它([控制器释放])结束。

不应该在下一行(if(nil == controller.view.superview))产生一个EXC_BAD_ACCESS错误,因为我们刚刚发布了RELEASED控制器?

看看alloc和release之间的界限。

[viewControllers replaceObjectAtIndex:page withObject:controller]; 

viewControllers数组将保留控制器。

但是,这不是好代码。正是你所说的原因。一见不见。

+0

我的理解是,viewControllers将保留的ViewController肯定的,但自从_ [控制器发布] _,它应该不再是通过访问*控制器指针应该如何?只能通过[viewControllers objectAtIndex:page]? – 2011-03-01 17:23:06

+0

当一个对象被保留时,它在内存中的位置保持不变。控制器指针仍然引用内存中的相同地址。一个版本不会改变指针和对象的地址。这就是为什么我们得到所有BAD_ACCESS错误。 – 2011-03-01 17:27:00

+0

所以是_ [controller] _ release调用是多余的并且不必要,因为我们通过将对象放入数组来保留对象? – 2011-03-01 17:36:42