2010-09-17 55 views
4

我有一些奇怪的事情與使用UINib,雖然我懷疑真正的問題可能被埋在別處。奇怪的問題使用UINib /指針去AWOL

我的應用程序使用tableview,由於其複雜性,在界面生成器中已經準備好了單元格的內容。對於新的單元格(而不是重用單元格),筆尖的內容使用UINib Class進行實例化。因爲每個單元只有一個nib用於減少每次加載文件的開銷,所以我將一個UINib作爲屬性cellNib添加到我的viewcontroller子類中,該子類在執行viewDidLoad時加載一次。

現在是奇怪的部分。一切工作正常,tableview被填充其數據,並且所有的單元格都被設置爲它們應該是的筆尖內容。但只要我滾動tableview,應用程序崩潰。
調用堆棧給出了這個:- [NSCFNumber instantiateWithOwner:options:]:無法識別的選擇器發送到實例 顯然,從cellNib再次實例化內容的消息已發送到錯誤的對象。消息發送到的對象時常不同,所以會出現隨機事件。

我不明白它 - 爲什麼它加載tableview時,大約10倍的工作,但不是當tableview被滾動時不再是?

如果我創建一個新實例的UINib 每個時間(如我的代碼所示),那麼一切都很好,包括滾動。

我在哪裏犯了一個錯誤?我的UINib屬性的指針是否會變成awol?如果是這樣,爲什麼?

下面是我使用的代碼(我刪除了所有的數據加載和其他的東西,使其更易於閱讀):

@interface NTDPadViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> { 

    NSManagedObjectContext *managedObjectContext; 
    NSMutableArray *ntdArray; 
    IBOutlet UITableView *ntdTableView; 
    UINib *cellNib; 

} 

@property(nonatomic,retain) NSManagedObjectContext *managedObjectContext; 
@property(nonatomic,retain) NSMutableArray *ntdArray; 
@property(nonatomic,retain) UITableView *ntdTableView; 
@property(nonatomic,retain) UINib *cellNib; 

@end 

實施:

@implementation NTDPadViewController 

@synthesize managedObjectContext; 
@synthesize ntdArray; 
@synthesize ntdTableView; 
@synthesize cellNib; 

-(void)viewDidLoad { 

    [super viewDidLoad]; 
    cellNib = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 

} 

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 
     [cell setBackgroundColor:[UIColor clearColor]]; 

     // These two should work equally well. But they don't... of course I'm using only one at a time ;) 
     // THIS WORKS: 
     UINib *test = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 
     NSArray *nibArray = [test instantiateWithOwner:self options:nil]; 

     // THIS DOESN'T WORK: 
     NSArray *nibArray = [cellNib instantiateWithOwner:self options:nil]; 

     [[cell contentView] addSubview:[nibArray objectAtIndex:0]]; 

    } 

    return cell; 
} 

非常感謝!

回答

7

此行的autorelease d實例分配給cellNib

cellNib = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 

這意味着,下面一行:

NSArray *nibArray = [cellNib instantiateWithOwner:self options:nil]; 

... cellNib已經釋放時,其相關的自動釋放池被抽乾並使用它將導致未定義的行爲。

如果您想讓cellNib繼續擁有它,例如通過使用聲明的屬性:

self.cellNib = [UINib nibWithNibName:@"NTDCell" bundle:nil]; 
+0

你是絕對正確的。現在正在工作。你能解釋一下爲什麼cellNib =和self.cellNib =有區別嗎?我一直認爲在一個對象通過自我來引用一個屬性的上下文中。是「可選的」...(愚蠢的我) – Toastor 2010-09-17 10:16:38

+0

@ Toastor:這兩個變種做了完全不同的事情。 'self.cellNib = ...'是調用setter的「點語法」,在你的案例中保留。 'cellNib = ...'只是直接分配給伊娃,覆蓋以前的指針值。請參閱[聲明的屬性部分](http://developer.apple。com/library/mac /#documentation/cocoa/conceptual/objectivec/Articles/ocProperties.html)以獲取詳細信息。 – 2010-09-17 10:24:45

+0

太棒了!再次感謝! – Toastor 2010-09-17 10:42:04