UITableView падает при прокрутке - PullRequest
3 голосов
/ 12 мая 2011

Мои друзья пытались создать собственное приложение для группы, и я экспериментировал с использованием пользовательского TableViewCell для новостных статей, которые появляются на сайте. Моя главная цель - получить все данные с веб-сайта, сохранить их в NSMutableArray, а затем отобразить их в моих пользовательских ячейках.

Приложение работает нормально, когда загружает первые 5-6 ячеек. Однако, когда я начинаю прокручивать, приложение вылетает. Я точно определил метод cellForRowAtIndexPath:. Используя GDB, я также обнаружил, что после создания моих данных NSMutableArray и после запуска программы, после прокрутки, мой массив, кажется, автоматически высвобождается. Я не уверен, почему это происходит. Вот что у меня есть для моего кода:

В HomeViewController.h:

@interface HomeViewController : UIViewController {
    NSArray *results;
    NSMutableArray *titles;
    NSMutableArray *dates;
    NSMutableArray *entries;
}

@property (nonatomic, retain) NSMutableArray *titles;
@property (nonatomic, retain) NSMutableArray *dates;
@property (nonatomic, retain) NSMutableArray *entries;

@end

В HomeViewController.m:

- (void)viewDidLoad {
[super viewDidLoad];
titles = [[NSMutableArray alloc] init];
dates = [[NSMutableArray alloc] init];
entries = [[NSMutableArray alloc] init];

while((i+1) != endIndex){   
    NSString *curr_title = [[NSString alloc] init]; 
    NSString *curr_date = [[NSString alloc] init];
    NSString *curr_entry = [[NSString alloc] init];

    //do some character iterations across a string

    [titles addObject:curr_title];
    [dates addObject:curr_date];
    [entries addObject:curr_entry];

    [curr_title release];
    [curr_date release];
    [curr_entry release];
}
}

// здесь больше кода, удалено

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

static NSString *CellIdentifier = @"NewsCell";


NewsCell *cell = (NewsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {
    NSArray *topLevelObjects = [[NSBundle mainBundle]
                                loadNibNamed:@"NewsCell"
                                owner:self options:nil];
//  cell = [topLevelObjects objectAtIndex:0];
    for(id currentObject in topLevelObjects){
        if([currentObject isKindOfClass:[UITableViewCell class]]){
            cell = (NewsCell *)currentObject;
            break;
        }
    }

}
NSLog(@"%d", indexPath.row);
NSLog(@"%d", titles.count);
cell.cellTitle.text = [titles objectAtIndex:indexPath.row];
cell.datePosted.text = [dates objectAtIndex:indexPath.row];
cell.preview.text = [entries objectAtIndex:indexPath.row];

return cell;
}

Снова появляются первые 5-6 клеток. После прокрутки я попытался сделать po titles и получил эту ошибку:

Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x00000009 0x011b309b in objc_msgSend ()

Я пытался распределить массивы в initWithNibName:, но, похоже, это мало что дало. Я попытался переместить весь код в viewDidLoad:, а затем вызвать [super viewDidLoad], и он также дал те же результаты. Извините, что это так долго, но я решил, что люди должны увидеть мой код.

Ответы [ 3 ]

2 голосов
/ 12 мая 2011

Я не вижу ничего явно неправильного в коде, который вы разместили. Попробуйте включить переменную окружения NSZombieEnabled . Это предотвращает освобождение объектов, поэтому при сбое приложения вы можете определить, какой объект вызвал проблему.

Кроме того, вместо циклического перебора массива объектов, возвращаемых loadNibNamed:owner:options, вы должны назначить нужный объект свойству IBOutlet вашего класса. См. Загрузка пользовательских ячеек табличного представления из файлов пера для примера.

<ч />

Из нового отправленного вами кода извлечено следующее:

NSString *curr_title = [[NSString alloc] init];

//do some character iterations across a string

[titles addObject:curr_title];

[curr_title release];

NSString не является изменяемой (как NSMutableString). Вы намеренно добавляете пустые строки в массив заголовков?

<ч />

В ответ на ваш комментарий: stringByAppendingString создает новый автоматически освобожденный объект NSString.

NSString *curr_title = [[NSString alloc] init];

// this leaks the original NSString object (curr_title no longer points to it);
// curr_title now points to a new, autoreleased NSString
curr_title = [curr_title stringByAppendingString:@"..."];

[titles addObject:curr_title];

// releasing the autoreleased NSString will cause your application to crash!
[curr_title release];
0 голосов
/ 12 мая 2011

* EXC_BAD_ACCESS * - верный признак того, что один из ваших объектов был освобожден (или не был сохранен должным образом). NSZombieEnabled ваш друг здесь, как и полагает titaniumdecoy - выяснить, какой объект был выпущен - это полдела.Просто обязательно выключите его перед выпуском приложения, потому что (как указал titaniumdecoy) оно препятствует освобождению объектов.

Я обычно использую комбинацию NSZombieEnabled и хорошо расположенных точек останова (поэтому я могу пройти черезкод, пока он не падает), чтобы выяснить, где проблема возникает в коде.Тогда обычно достаточно просто вернуться назад, чтобы выяснить, где объект был отпущен.

0 голосов
/ 12 мая 2011

Возможно, проблема в реализации NewsCell, все ваши свойства там сохранены?

Кроме того, есть ли причина, по которой HomeViewController является подклассом UIViewController, а не UITableViewController?

И это должно работать просто отлично:

NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewsCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...