2011-12-07 38 views
1

我在我的應用程序中使用自定義單元格。當用戶點擊一個錶行,將出現一個自定義單元格:自定義單元格創建250次後應用程序崩潰

#import "SonaraamatuKontroller.h" 
#import "TolkegaLahter.h" 

//Lahtris kasutatava teksti fondi suurus 
#define FONT_SIZE 14.0f 
//Tabelilahtri laius 
#define CELL_CONTENT_WIDTH 320.0f 
//Tabeli sisu äärise kaugus lahtri servadest 
#define CELL_CONTENT_MARGIN 5.0f 

@implementation SonaraamatuKontroller 
@synthesize sonaraamatuSisukord=sonaraamatuSisukord; 
@synthesize sonaraamatuTabel; 
@synthesize valitudLahtriIndexPath; 
@synthesize tolkegaLahter; 
@synthesize audioPleier; 
@synthesize sonaraamatuFailinimi; 
@synthesize sonaraamatuNavribaNimi; 


- (void)viewDidLoad { 
[super viewDidLoad]; 

NSString *error; 
NSPropertyListFormat format; 

NSString *localizedPath = [[NSBundle mainBundle] pathForResource:sonaraamatuFailinimi ofType:@"plist"]; 
NSData *plistData = [NSData dataWithContentsOfFile:localizedPath]; 

NSArray *sisukordData = [NSPropertyListSerialization propertyListFromData:plistData 
                 mutabilityOption:NSPropertyListImmutable 
                    format:&format 
                 errorDescription:&error]; 


if (sisukordData) { 
    self.sonaraamatuSisukord = [NSMutableArray arrayWithCapacity:[sonaraamatuSisukord count]]; 
    for (NSDictionary *sisukordDictionary in sisukordData) { 
     [self.sonaraamatuSisukord addObject:sisukordDictionary]; 
    } 
} 

self.navigationItem.title=sonaraamatuNavribaNimi; 
} 



- (void)didReceiveMemoryWarning { 
// Releases the view if it doesn't have a superview. 
[super didReceiveMemoryWarning]; 

// Release any cached data, images, etc that aren't in use. 
} 

- (void)viewDidUnload { 
//Teise vaatesse liikumisel pannakse audiopleier seisma 
[audioPleier stop]; 
// Release anything that can be recreated in viewDidLoad or on demand. 
// e.g. self.myOutlet = nil; 
} 


#pragma mark - 
#pragma mark UITableViewDataSource 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    //Loeme tabeli sektsioonide arvu - kuna praegusel juhul on sisukorras ainult üks liige (sõnaraamat "Item 0"), siis on ka sektsioone üks 
    return [sonaraamatuSisukord count]; 
} 



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    //Loeme vastavas sektsioonis asuvate ridade arvu 
    NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:section] objectForKey:@"Items"]; 
    return [sisukordItems count];  
} 


- (CGFloat) tableView : (UITableView *) tableView 
heightForRowAtIndexPath: (NSIndexPath *) indexPath { 
if(valitudLahtriIndexPath != nil 
    && [valitudLahtriIndexPath isEqual:indexPath]) 
    return 95; 


    NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:@"Items"]; 

    NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row]; 

    NSString *text = [sisukordItem objectForKey:@"Valjend"];  

    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f); 


    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap]; 

    CGFloat height = MAX(size.height, 25.0f); 
    return height + (CELL_CONTENT_MARGIN * 2); 
} 


#pragma mark - 
#pragma mark UITableViewDelegate 

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

if((valitudLahtriIndexPath != nil) 
    && [valitudLahtriIndexPath isEqual:indexPath] 
    ) 

{ //NSLog (@"ValitudPath: %@", valitudLahtriIndexPath); 
    static NSString *TolkegaLahtriTunnus = @"TolkegaLahter"; 

    TolkegaLahter *cell = (TolkegaLahter *)[tableView dequeueReusableCellWithIdentifier:TolkegaLahtriTunnus]; 

    if (cell == nil) {  
     [[NSBundle mainBundle] loadNibNamed:@"TolkegaLahter" owner:self options:nil]; 
     cell = tolkegaLahter; 


    [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 

    //Lisame gradiendi: 
    CAGradientLayer *gradient = [CAGradientLayer layer]; 
    [gradient setCornerRadius:9.0f]; 
    //[gradient setMasksToBounds:YES]; 
    //[gradient setBorderWidth:0.8f]; 
    //[gradient setBorderColor:[[UIColor darkGrayColor] CGColor]]; 
    gradient.frame = cell.bounds; 
    gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.122 green:0.2 blue:1 alpha:0.95] CGColor], (id)[[UIColor colorWithRed:0.041 green:0.1 blue:0.33 alpha:0.95] CGColor],(id)[[UIColor colorWithRed:0.122 green:0.2 blue:1 alpha:0.95] CGColor], nil]; 
    gradient.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.48],[NSNumber numberWithFloat:1.0], nil]; 
    [cell.layer insertSublayer:gradient atIndex:0]; 
    } 

    NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:@"Items"]; 
    NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row]; 

    cell.valjend.text=[sisukordItem objectForKey:@"Valjend"]; 
    cell.tolge.text=[sisukordItem objectForKey:@"Tolge"]; 


    [sonaraamatuTabel scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES]; 

    self.tolkegaLahter = nil; 

    return cell; 

} 

static NSString *CellIdentifier = @"Cell"; 

//Loome lahtrisse labeli 
UILabel *label = nil;  

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 


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

    //Esialgu on label tühi (asub punktis 0,0 ning on suurusega 0,0) 
    label = [[UILabel alloc] initWithFrame:CGRectZero]; 
    //Määrame reavahetuse stiili 
    [label setLineBreakMode:UILineBreakModeWordWrap]; 
    //Minimaalne fondi suurus on ülal defineeritud konstant 
    [label setMinimumFontSize:FONT_SIZE]; 
    //Esialgu on ridade arv 0 
    [label setNumberOfLines:0]; 
    //Määrame fondi. Selle suuruseks on ülal defineeritud konstant 
    [label setFont:[UIFont systemFontOfSize:FONT_SIZE]]; 
    [label setTag:1]; 

    //Lisame labelile piirid, et programmeerimise käigus oleks paremini näha, kuhu see lahtris paigutub 
    //[[label layer] setBorderWidth:2.0f]; 

    [[cell contentView] addSubview:label]; 

    [label release]; 
} 

    cell.selectionStyle = UITableViewCellSelectionStyleBlue; 
    cell.selectedBackgroundView=[[[UIView alloc] init] autorelease]; 
    cell.selectedBackgroundView.backgroundColor=[UIColor colorWithRed:0.537 green:0.18 blue:0.122 alpha:1.0]; 


    //Loome andmemassiivi sisukord objektidest (tuntakse ära võtme "Items" abil) andmemassiivi sisukordItems 
    NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:@"Items"]; 

    //Loome andmemassiivi sisukordItems objektidest sõnaraamatud sisukordItem 
    NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row]; 

    //Igas lahtris kuvatakse sellele vastavas sõnaraamatus sisalduva objekti "Valjend" väärtus 
    NSString *text = [sisukordItem objectForKey:@"Valjend"]; 


    //Sarnaselt lahtri kõrguse arvutamisele heightForRowAtIndexPath meetodis arvutame ka labeli 
    //kõrguse (sellele ei liideta ääriste kaugusi) 
    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f); 
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap]; 

    //Hangime labeli juhul kui see on nil (ja tegu ei ole vaate esialgse initsieerimisega ehk lahter ei ole nil) 
    if (!label) 
     label = (UILabel*)[cell viewWithTag:1]; 

    //Seame labeli teksti 
    [label setText:text]; 
    //Seame labeli piirjooned 
    [label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 25.0f))]; 


    label.textColor=[UIColor blackColor]; 
    label.font=[UIFont systemFontOfSize:14]; 
    label.backgroundColor=[UIColor clearColor];  


return cell; 
} 



- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {  


    self.valitudLahtriIndexPath = indexPath; 
    if(valitudLahtriIndexPath != nil //Kui see väärtus on tõene, 
     && [valitudLahtriIndexPath isEqual:indexPath]) { 

     [self.sonaraamatuTabel reloadData]; 


     NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:@"Items"]; 

     NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row]; 

     NSString*heliFailinimi=[sisukordItem objectForKey:@"HeliFailinimi"]; 

     NSError *setCategoryError = nil; 
     [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError]; 

     NSString *taustaHeliPath = [[NSBundle mainBundle] pathForResource:heliFailinimi ofType:@"m4a"]; 

     [audioPleier stop]; 

     NSURL *taustaHeliURL = [NSURL fileURLWithPath:taustaHeliPath]; 
     NSError *error; 
     audioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error]; 
     [audioPleier setDelegate:self]; // We need this so we can restart after interruptions 

     [audioPleier play];    
    } 

} 


- (void)viewWillAppear:(BOOL)animated 
{ 
NSIndexPath*selection = [self.sonaraamatuTabel indexPathForSelectedRow]; 
if (selection) 
    [self.sonaraamatuTabel deselectRowAtIndexPath:selection animated:YES]; 

[self.sonaraamatuTabel reloadData]; 
} 



- (void)dealloc { 
[valitudLahtriIndexPath release];  
[sonaraamatuSisukord release], sonaraamatuSisukord=nil; 
[audioPleier release]; 
[sonaraamatuFailinimi release]; 
[sonaraamatuNavribaNimi release]; 
[super dealloc]; 
} 


@end 

250之後水龍頭應用程序崩潰,我得到的消息:

終止應用程序由於未捕獲的異常「NSInternalInconsistencyException」,原因:'無法加載捆綁中的NIB:名稱爲'TolkegaLahter'的'NSBundle(已加載)'

這種行爲的原因是什麼?內存泄漏的地方?

編輯

這是關於AVAudioPlayer,這是一次又一次的創造,但沒有公佈。 所以,我取代

audioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error]; 

 AVAudioPlayer*ajutineAudioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error]; 
     self.audioPleier=ajutineAudioPleier; 
     [ajutineAudioPleier release]; 

回答

1

是你的問題的代碼的cellForRowAtIndexPath方法?從您的問題中不清楚這些代碼的位置或執行時間。

如果是(或者,對於其中的一些,哪怕是沒有),有幾個問題是:

  • 如果離隊方法帶給你不必返回細胞東西回來
  • 您沒有配置的電池,如果出列方法給你帶來的東西回來
  • 這使我想到的是你沒有設置複用標識符在您的自定義單元格的子類在Interface Builder
  • 這意味着你每創建一個新的單元格都可以給你一個崩潰,如果你有足夠數量的細胞
  • 滾動調用似乎很奇怪,(這隻會是奇數,如果這你的cellForRowAtIndexPath方法)

如果您反覆從筆尖加載,你可能要檢查出UINib以及。

編輯

看着你完整的代碼後,我認爲這個問題是你的音頻播放器,您創建和每一個被選中的單元格時配置一個新的,這是泄漏。

您應該在您的viewDidLoad上設置音頻播放器,並在您選擇單元格時告訴它播放特定的聲音。

+0

是的,它在cellForRowAtIndexPath方法中。不幸的是,我不在我的Mac不幸的是,所以我不能檢查是否設置了重用標識符。但滾動調用按我的預期工作 - 自定義單元格比平常單元格更高,當用戶點擊它時,在某些情況下會部分隱藏。滾動調用有助於使其可見。 – Shiim

+0

那麼tap操作告訴tableview重新加載該行的單元格?你能否用這個細節更新問題(當你回到你的mac時,顯然是:)) – jrturton

+0

這裏粘貼了我所有的m文件代碼。標識符被設置在我的Custom Cell的NIB中,現在應該返回並配置單元格(之前它也是這樣,但是我誤解了某人的建議並以一種不返回單元格的方式更改了代碼)。無論如何,它仍然會給出同樣的錯誤。 – Shiim

1

嘗試更換

[[NSBundle mainBundle] loadNibNamed:@"TolkegaLahter" owner:self options:nil]; 
cell = tolkegaLahter; 

cell = [[[TolkegaLahter alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: TolkegaLahtriTunnus] autorelease]; 
self.tolkegaLahter = [[[NSBundle mainBundle] loadNibNamed:@"TolkegaLahter" owner:self options:nil] lastObject]; 
cell = self.tolkegaLahter; 
+0

謝謝,但我仍然使用你的建議得到相同的錯誤 – Shiim

相關問題