2012-02-01 95 views
4

在用戶遇到同樣問題的情況下,我有一些StackOverflow問題。但是,他們的解決方案都不符合我的情況。 (見herehereherehere對於一些我讀過,但做題還沒有找到有幫助的。)UIButton觸及IBAction,導致EXC_BAD_ACCESS與ARC

就我而言,我有一個NIB有一對夫婦UIButton S,與相關的控制器查看。這個視圖對我的項目來說比較古老,直到今天我才能夠毫無麻煩地使用這些按鈕。在做了一些與按鈕行爲無關的代碼更改後,我遇到了一個錯誤,導致應用程序崩潰,打破了main()函數中的代碼,並在我觸摸任意按鈕時給我一個EXC_BAD_ACCESS錯誤消息在我的觀點。

這是怎麼發生的呢?我實際上已經註釋了幾乎所有的功能代碼,尤其是我今天早些時候修改的功能代碼,並且我仍然無法阻止發生的錯誤。

我的項目使用自動引用計數,我以前沒有看到過這個錯誤。此外,我沒有修改NIB,也沒有與按鈕相關的IBAction,所以我沒有看到會導致這種情況。停止錯誤的唯一方法是將我的NIB中的我的UIButton與我的Controller View頭文件中定義的IBAction方法取消關聯。

我的用例唯一的「獨特」方面是我在另一個子視圖控制器中加載這個視圖的一個或兩個實例。加載的斷開視圖的實例數取決於數組中的對象數。下面是我用來實例化和加載這些視圖作爲另一個視圖的子視圖的代碼。

//Called else where, this starts the process by creating a view that 
//will load the problematic view as a sub-view either once or twice. 
- (id)initWithPrimarySystemView:(SystemViewController *)svc 
{ 
    //First we create our parent, container view. 
    self = [super initWithNibName:@"ContainerForViewInstaniatedFromArrayObjs" bundle:nil]; 
    if (self) 
    { 
     //Assign parent DataModel to local instance 
     [self setDataModel:((DataModelClass*)svc.DataModel)]; 
     for (AnotherModel* d in DataModel.ArrayOfAnotherModels) 
     { 
      //Instantiate the SubViewController. 
      SubViewController* subsvc = [[SubViewController alloc] 
              initWithNibName:@"Subview" 
              bundle:nil 
              subviewPosition:d.Position ]; 

      //Add the SubViewControllers view to this view. 
      [subsvc.view setFrame:CGRectMake((d.Position-1)*315, 0, 315, 400)]; 
      [self.view addSubview:subsvc.view]; 
     } 
     [self setDefaultFrame: CGRectMake(0, 0, 640, 400)]; 
    } 
    return self; 
} 

這工作完全和以前,挖掘時甚至都沒有引起與分別對相關視圖中的按鈕任何麻煩,不過,現在所有UIButton小號崩潰的應用程序。

SubViewController的初始化函數以及viewDidLoad方法不包含除創建新ViewController時添加的標準自動生成代碼之外的其他內容。

我該如何解決或診斷此問題?

回答

8

看到我的評論在您的代碼:

{ 
    SubViewController* subsvc = [[SubViewController alloc] initWithNibName:@"Subview" bundle:nil subviewPosition:d.Position ]; 
    //!i: By default, subsvc is a __strong pointer, so your subview has a +1 retain count 
    // subsvc owns subsvc.view, so subsvc.view has a +1 retain count as well 

    //Add the SubViewControllers view to this view. 
    [subsvc.view setFrame:CGRectMake((d.Position-1)*315, 0, 315, 400)]; 

    [self.view addSubview:subsvc.view]; 
    //!i: This bumps subsvc.view to +2, as self.view strong-references it 

    //!i: subsvc is going out of scope, so the reference count on subsvc will drop 
    // to 0 and it is dealloc'd. subsvc.view's retain count drops to +1, as it 
    // is still referenced by self.view 
    // 
    // Most likely, in -[SubViewController dealloc], you were not doing a 
    // setTarget:nil, setAction:nil on the button. Thus, the button now 
    // has a dangling pointer and will crash when hit 
} 

爲了解決這個問題,每個SubViewController實例添加到由主視圖CONTROLER擁有的陣列。這將保持SubViewController實例接收按鈕水龍頭。

+0

有趣的是,當我到我的桌子時,我會試試這個。我可以明白爲什麼這會解決問題,但我有點困惑 - 我已經有了這個機制幾個星期。我沒有遇到任何問題,我也沒有調整過相關的代碼。如果你說的是問題,這似乎總是一個問題,而不是在任意一天神奇地出現。你有什麼線索爲什麼這可以在某些情況下工作? – RLH 2012-02-02 14:03:02

+0

謝謝,這工作! – RLH 2012-02-02 15:40:18

+0

你剛剛升級到ARC嗎?這看起來像是手工引用計數中的泄漏。也有可能你有其他東西保留SubViewController並保持它之前保持活着 - 如果你正在使用定時器,可能是運行循環,或者如果你是動畫的話可能是UIViewAnimation。 – iccir 2012-02-03 01:42:02

1

確保在您的dealloc您撥打:

[按鈕removeTarget:無 行動:NULL forControlEvents:UIControlEventAllEvents]。

雖然你雖然在ARC中不需要「dealloc's」,但是你可以這樣做,因爲iccir解釋了什麼。

+0

如果所有這些UIView對象都在IB中創建並通過IBOutlets連接,這是否有必要?我從來沒有閱讀說明來做到這一點。 – RLH 2012-02-21 15:07:22

+1

是的 - 尤其是IB。 IB創建,但它不處理你的對象的破壞。 – dacopenhagen 2012-03-27 19:10:21