2013-07-14 27 views
1

我有一個視圖控制器,名爲AllThingsViewController動態創建其他視圖控制器,名爲ThingViewController,並將其頂級視圖添加到UIScrollView。 (我寫的專有代碼,所以我改變類的名字,但我的代碼的結構是完全一樣的。)ObjC:ARC發佈動態創建視圖控制器太早

下面是其的loadView方法包括:

NSArray *things = [[ThingDataController shared] getThings]; 

if ([things count] == 0) { 
    // code in this block is not relevant as it's not being executed... 
} else { 

    for(unsigned int i = 0; i < [things count]; ++i) { 
     ThingViewController *thingViewController = [[ThingViewController alloc] init]; 
     [thingViewController loadView]; 

     [scrollView addSubview:thingViewController.topView]; 
     thingViewController.topView.frame = CGRectNewOrigin(thingViewController.topView.frame, 
       0, thingViewController.topView.frame.size.height*i); 

     [thingViewController displayThing:thing[i]]; 
    } 
} 

ThingViewController的的loadView方法是這樣的:

- (void)loadView 
{ 
    NSArray *topLevelObjs = nil; 
    topLevelObjs = [[NSBundle mainBundle] loadNibNamed:@"ThingView" owner:self options:nil]; 
    if (topLevelObjs == nil) 
    { 
     NSLog(@"Error: Could not load ThingView xib\n"); 
     return; 
    } 
} 

當我的應用程序啓動時的一切顯示正常,直到我試圖挖掘存在於廈門國際銀行通過ThingViewController被加載,此時它崩潰,由於異常的一個按鈕: 「無法識別的選擇器發送o實例「。看起來ARC很早就釋放了我的ThingViewController實例。

看着我的代碼,我想這是因爲他們沒有被扶着任何東西,所以我創建了一個NSMutableArray在我AllThingsViewController類的實例變量,並開始正是如此添加ThingViewControllers它:

NSArray *things = [[ThingDataController shared] getThings]; 

if ([things count] == 0) { 
    // not being executed... 
} else { 

    for(unsigned int i = 0; i < [things count]; ++i) { 
     ThingViewController *thingViewController = [[ThingViewController alloc] init]; 
     [thingViewController loadView]; 

     [scrollView addSubview:thingViewController.topView]; 
     thingViewController.topView.frame = CGRectNewOrigin(thingViewController.topView.frame, 
       0, thingViewController.topView.frame.size.height*i); 

     [thingViewController displayThing:thing[i]]; 

     [allThingsViewControllers addObject:thingViewController]; 
    } 
} 

但是,即使將這些對象添加到數組中,它也不會改變任何內容。最後,只是爲了確認,這是ARC早期釋放它,我改變了「thingViewController」是在AllThingsViewController一個實例變量和變化:

ThingViewController *thingViewController = [[ThingViewController alloc] init]; 

是:

thingViewController = [[ThingViewController alloc] init]; 

果然,最後當我點擊它的按鈕時,可滾動列表中的項不會崩潰,但其他項會這樣做,因爲它的ThingViewController沒有被釋放。

我對ARC還比較陌生,但是在搜索一堆Google之後,我不知道如何解決這個問題。我該怎麼辦?

+1

請顯示*完整*「無法識別的選擇器...」錯誤消息。 –

+0

無法識別的選擇器錯誤通常不表示某些內容發佈得太早。它抱怨什麼是無法識別的選擇器? – Jumhyn

+1

一個完全不同的對象,那麼當我點擊一個按鈕時,我的視圖控制器正試圖響應選擇器。我所做的研究表明,這是因爲視圖控制器正在被釋放,並且一個新的對象現在居住在這部分內存中。另外,每次運行它都是嘗試執行選擇器的另一種對象。此外,如果我明確地將「thingViewController」作爲一個實例變量(因此肯定有強烈的參考),它會停止對至少一個視圖控制器的崩潰,所以我很確定問題是它也被釋放早。 – GuyGizmo

回答

3

幾件事情。

問題1:

這看起來像你的錯誤的原因:

[allBillViewControllers addObject:billViewController]; 

它應該是:

[allBillViewControllers addObject:thingViewController]; 

,對嗎?

問題2

您沒有正確添加視圖控制器到您的視圖層次。刪除子視圖控制器時,

[self addChildViewController:childViewController]; 
[childViewController.view setFrame:targetFrame]; 
[scrollView addSubview:childViewController.view]; 
[childViewController didMoveToParentViewController:self]; 

而且類似:它應該是這個

[childViewController willMoveToParentViewController:nil]; 
[childViewController.view removeFromSuperview]; 
[childViewController removeFromParentViewController]; 

問題3

,一定不要調用loadView明確視圖控制器上。無論何時訪問視圖控制器的view屬性,它都會被UIKit調用。

問題4

必須在子視圖控制器的view添加到您的滾動視圖,其視圖層次不是一個武斷的子視圖topView。重構你的ThingViewController類,使自己變得更簡單。 :-)

2

讓我們看看你的代碼:

for(unsigned int i = 0; i < [things count]; ++i) { 
    ThingViewController *thingViewController = [[ThingViewController alloc] init]; 
    [thingViewController loadView]; 

    [scrollView addSubview:thingViewController.topView]; 
    thingViewController.topView.frame = CGRectNewOrigin(thingViewController.topView.frame, 
      0, thingViewController.topView.frame.size.height*i); 

    [billViewController displayThing:thing[i]]; 

    [allBillViewControllers addObject:billViewController]; 
} 

的for循環執行每個循環之後,什麼也不會有很強的參考ThingViewController。因此,它被釋放和銷燬。

如果ThingViewControllerUIViewController的子類,那麼它應該成爲scrollview視圖控制器的「子視圖控制器」。我推薦閱讀the section on from the View Controller Programming Guide on creating custom container view controllers(即封裝並顯示其他視圖控制器的視圖控制器)。