iphone - 创建自定义单元格 250 次后应用程序崩溃

标签 iphone ios

我在我的应用中使用自定义单元格。当用户点击表格行时,会出现一个自定义单元格:

#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”而终止应用程序,原因:“无法在 bundle 中加载 NIB:名称为“TolkegaLahter”的“NSBundle(已加载)”

这种行为的原因可能是什么?某处发生内存泄漏?

编辑

是关于AVAudioPlayer的,一次又一次创建,但没有发布。 所以,我更换了

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

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

最佳答案

您问题中的代码是 cellForRowAtIndexPath 方法吗?从您的问题中不清楚这段代码在哪里或何时执行。

如果是(或者,对于其中一些,即使不是),它也有几个问题:

  • 如果 dequeue 方法给你带回了一些东西,你就不会返回单元格
  • 如果 dequeue 方法给你带回了一些东西,你就没有配置单元
  • 这让我认为您没有在界面构建器的自定义单元格子类中设置重用标识符
  • 这意味着你每次都在创建一个新的单元格,如果你有足够数量的单元格,这可能会让你崩溃
  • 滚动调用看起来很奇怪(如果这是 您的 cellForRowAtIndexPath 方法,这只会很奇怪)

如果您重复从 nibs 加载,您可能还想查看 UINib

编辑

在查看您的完整代码后,我认为问题出在您的音频播放器上,每次选择单元格时您都在创建和配置一个新的播放器,这正在泄漏。

您应该只在 viewDidLoad 上设置音频播放器,并告诉它在您选择单元格时播放特定的声音。

关于iphone - 创建自定义单元格 250 次后应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8411589/

相关文章:

iphone - ImagePicker View Controller - 图像路径 - iphone

iphone - 在实现应用内购买期间使产品 ID 无效

css - iPhone Safari CSS 旋转错误

iphone - 我可以用 FXLabel *替换* UIButton 上的 UILabel 吗?

iphone - 从应用程序包读取文本文件

ios - CocoaPods 不工作

iphone - 稍后从UIImagePickerController压缩视频吗?

ios - 在 opengl-es iOS 中建立索引

ios - 如何在当前项目中搜索任何 UIWebView 组件使用情况?

ios - 在 Swift 中使用 Apple 的可达性类