1

まず、私の英語を許してください。

私はiPhone SDK、Obj-Cについて学び、UITableViewアプリを作ろうとしています。しかし、テーブルをスクロールするとアプリがクラッシュします。検索しましたが、問題を解決できません。ここに質問を投稿して、助けを求めます。

TMTMemberListTableViewController.h

@interface TMTMemberListTableViewController : UITableViewController
{
    NSMutableArray *familyMembers;
    sqlite3 *database;
}

@property (nonatomic, retain) NSMutableArray *familyMembers;

- (void) configureCell:(TMTFamilyMemberCell *)cell withFamilyMember:(TMTFamily *)member;

@end

TMTMemberListTableViewController.m

@interface TMTMemberListTableViewController (Private)
    - (void) loadMemberListFromDatabase;
@end

@implementation TMTMemberListTableViewController

@synthesize familyMembers;

- (void) loadMemberListFromDatabase
{
    familyMembers = [[NSMutableArray alloc] init];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"easycook.sqlite"];
    if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
    {
        const char *sql = "SELECT member_id from family";
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK)
        {
            while (sqlite3_step(statement) == SQLITE_ROW)
            {
                NSString *memberID = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 0)];
                TMTFamily *member = [[TMTFamily alloc] initWithMemberID:memberID database:database];
                [familyMembers addObject:member];
                [member release];
            }
        }
        sqlite3_finalize(statement);
    }
    else
    {
        sqlite3_close(database);
        NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.clearsSelectionOnViewWillAppear = NO;

    self.navigationItem.rightBarButtonItem = self.editButtonItem;
    [self loadMemberListFromDatabase];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [familyMembers count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //static NSString *MyIdentifier = @"MyIdentifier";

    TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:nil];
    if (cell == nil)
    {
        cell = [[[TMTFamilyMemberCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    TMTFamily *member = [familyMembers objectAtIndex:indexPath.row];
    // Set up the cell
    [self configureCell:cell withFamilyMember:member];
    [member release];
    return cell;
}

- (void) configureCell:(TMTFamilyMemberCell *)cell withFamilyMember:(TMTFamily *)member
{
    cell.familyMember = member;
    cell.memberNameLabel.text = member.description;
}
- (void)dealloc
{
    NSLog(@"Dealloc");
    [familyMembers release];
    [super dealloc];
}

テーブルをスクロールすると、アプリが EXC_BAD_ACCESS でクラッシュします

[self configureCell:cell withFamilyMember:member];

cell.memberNameLabel.text = member.description;
4

2 に答える 2

1

まず、Stack Overflowへようこそ。そして、iOS開発の世界へようこそ。

コードには多くの問題があります。Appleデベロッパアカウントをお持ちの場合は、2012 WWDCセッションビデオにアクセスして、ModernObjectiveCセッションについての話をご覧になることを強くお勧めします。 https://developer.apple.com/videos/wwdc/2012/

コードを見ると、アクセス不良は、すでにリリースされているオブジェクトか、空のセルのいずれかである可能性があります。原因を特定するには、NSZombiesを有効にする必要があります。これを行うには、次に示すようにツールバーのプロジェクト名をクリックします。

ここに画像の説明を入力してください

この例では、PartialTransparentcyと呼ばれています(つづりは気にしないでください)。そのボタンをクリックしたら、[スキームの編集]ボタンをクリックすると、オプションのリストが表示されます。[ゾンビオブジェクトを有効にする]をクリックすることをお勧めします。表示されない場合は、[診断]タブを押してください。

ここに画像の説明を入力してください

次に、コードを実行すると、悲しみを与えているオブジェクトがログに記録されます。ゾンビオブジェクトは非常に高価であることを覚えておいてください。それらを有効にしてアプリを送信すると、自動的に拒否されます。

セル初期化コードを見て最初に気付くのは、次のとおりです。

TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:nil];

セルを再利用するポイント全体を否定するnil識別子を送信しています。代わりに、古いセルを再利用する代わりに、行ごとに新しいセルを作成します。

したがって、この行のコメントを解除します。

static NSString *MyIdentifier = @"MyIdentifier";

デキューメソッドを次のように変更します。

TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];

Interface Builderでセルを構築する場合は、セルに識別子も指定する必要があります。これがクラッシュの原因である可能性があります。

次に...sqlliteコードを別のオブジェクトにカプセル化する必要があります。ビューコントローラがそれを知る理由はありません。また、コアデータを実際に調査する必要があります。デフォルトはsqlliteバッキングストアです。それはまた、かなり素晴らしい技術です。

そして最後に、ARCを見てください。アプリケーションのユーザーエクスペリエンスに集中できるように、コンパイラにメモリ管理の面倒な作業を処理させます。

それがお役に立てば幸いです!

于 2012-11-03T17:26:14.143 に答える
1

この行は保持カウンターをインクリメントしていません: TMTFamily *member = [familyMembers objectAtIndex:indexPath.row]

したがって、次の行が問題です [member release];

オブジェクトを所有していない場合、オブジェクトを解放することはできません。次のように保持します。 TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] retain];

また

TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] copy];

releaseまたは言及を完全に削除します。

于 2012-11-03T17:22:32.970 に答える