iPhone - didSelectRowAtIndexPath - выбор строки 26 или более загадка - PullRequest
1 голос
/ 18 января 2010

Мой UITableView имеет до 50 строк в каждом разделе, заполненном словарем plist, который содержит массивы (секции), которые содержат массивы (объекты строк), которые содержат две строки (заголовок / имя файла и расширение файла).

Выберите строки 1 - 25 (пункт 0-24), и все будет нормально. Но выберите строку больше 26 (элемент 25), и приложение вылетает. Я новичок во всем этом, и я пытался найти ответ, но я не знаю, как это исследовать. Могут ли таблицы иметь только 25 строк на раздел?

Есть идеи? Спасибо!

Jon

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

    NSUInteger section = [indexPath section];
    NSUInteger row = [indexPath row];
    NSMutableString *key = [categories objectAtIndex:section];
    NSMutableArray *sound = [categoriesSounds objectForKey:key];
    NSMutableString *soundName = [[sound objectAtIndex: row] objectAtIndex: 0];
    NSMutableString *soundOfType = [[sound objectAtIndex: row] objectAtIndex: 1];


    if (leftSwitch.on == YES) {
        showLeft.text = soundName;
        left    = [[NSBundle mainBundle] pathForResource:(@"%@", soundName) ofType:(@"%@", soundOfType)];
        AudioServicesCreateSystemSoundID((CFURLRef)[NSURL
                                                    fileURLWithPath:left], &soundNegZ); 
        AudioServicesPlaySystemSound (soundNegZ); 

        if (indexPath != leftOldIndexPath) {
            UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
            newCell.accessoryType = UITableViewCellAccessoryCheckmark;
            UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:leftOldIndexPath];
            oldCell.accessoryType = UITableViewCellAccessoryNone;
            leftOldIndexPath = indexPath;
        }
        [tableView deselectRowAtIndexPath:indexPath animated:YES];


    }

    if (downSwitch.on == YES) {
        showDown.text = soundName;
        down    = [[NSBundle mainBundle] pathForResource:(@"%@", soundName) ofType:(@"%@", soundOfType)];
        AudioServicesCreateSystemSoundID((CFURLRef)[NSURL
                                                    fileURLWithPath:down], &soundNegX); 
        AudioServicesPlaySystemSound (soundNegX);

        if (indexPath != downOldIndexPath) {
            UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
            newCell.accessoryType = UITableViewCellAccessoryCheckmark;
            UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:downOldIndexPath];
            oldCell.accessoryType = UITableViewCellAccessoryNone;
            downOldIndexPath = indexPath;
        }
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    }

    if (rightSwitch.on == YES) {
        showRight.text = soundName;
        right    = [[NSBundle mainBundle] pathForResource:(@"%@", soundName) ofType:(@"%@", soundOfType)];
        AudioServicesCreateSystemSoundID((CFURLRef)[NSURL
                                                    fileURLWithPath:right], &soundPosX);    
        AudioServicesPlaySystemSound (soundPosX);

        if (indexPath != rightOldIndexPath) {
            UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
            newCell.accessoryType = UITableViewCellAccessoryCheckmark;
            UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:rightOldIndexPath];
            oldCell.accessoryType = UITableViewCellAccessoryNone;
            rightOldIndexPath = indexPath;
        }
        [tableView deselectRowAtIndexPath:indexPath animated:YES];

    }



}

Для "EXC_BAD_ACCESS" в консоли это вывод отладчика (трассировка ошибок отмечена звездочками):

0x91a6cec0  <+0000>  mov    0x8(%esp),%ecx
0x91a6cec4  <+0004>  mov    0x4(%esp),%eax
0x91a6cec8  <+0008>  cmp    $0xfffeb010,%ecx
0x91a6cece  <+0014>  je     0x91a6cf35 <objc_msgSend+117>
0x91a6ced0  <+0016>  test   %eax,%eax
0x91a6ced2  <+0018>  je     0x91a6cf1a <objc_msgSend+90>
0x91a6ced4  <+0020>  mov    (%eax),%edx
0x91a6ced6  <+0022>  push   %edi
**0x91a6ced7  <+0023>  mov    0x20(%edx),%edi** 
0x91a6ceda  <+0026>  push   %esi
0x91a6cedb  <+0027>  mov    (%edi),%esi
0x91a6cedd  <+0029>  mov    %ecx,%edx
0x91a6cedf  <+0031>  shr    $0x2,%edx
0x91a6cee2  <+0034>  and    %esi,%edx
0x91a6cee4  <+0036>  mov    0x8(%edi,%edx,4),%eax
0x91a6cee8  <+0040>  test   %eax,%eax
0x91a6ceea  <+0042>  je     0x91a6cef5 <objc_msgSend+53>
0x91a6ceec  <+0044>  cmp    (%eax),%ecx
0x91a6ceee  <+0046>  je     0x91a6cf00 <objc_msgSend+64>
0x91a6cef0  <+0048>  add    $0x1,%edx
0x91a6cef3  <+0051>  jmp    0x91a6cee2 <objc_msgSend+34>
0x91a6cef5  <+0053>  pop    %esi
0x91a6cef6  <+0054>  pop    %edi
0x91a6cef7  <+0055>  mov    0x4(%esp),%eax
0x91a6cefb  <+0059>  mov    (%eax),%eax
0x91a6cefd  <+0061>  jmp    0x91a6cf09 <objc_msgSend+73>
0x91a6ceff  <+0063>  nop    
0x91a6cf00  <+0064>  mov    0x8(%eax),%eax
0x91a6cf03  <+0067>  pop    %esi
0x91a6cf04  <+0068>  pop    %edi
0x91a6cf05  <+0069>  xor    %edx,%edx
0x91a6cf07  <+0071>  jmp    *%eax
0x91a6cf09  <+0073>  sub    $0x4,%esp
0x91a6cf0c  <+0076>  push   %ecx
0x91a6cf0d  <+0077>  push   %eax
0x91a6cf0e  <+0078>  call   0x91a6d33f <_class_lookupMethodAndLoadCache>
0x91a6cf13  <+0083>  add    $0xc,%esp
0x91a6cf16  <+0086>  xor    %edx,%edx
0x91a6cf18  <+0088>  jmp    *%eax
0x91a6cf1a  <+0090>  call   0x91a6cf1f <objc_msgSend+95>
0x91a6cf1f  <+0095>  pop    %edx
0x91a6cf20  <+0096>  mov    0xe79d961(%edx),%eax
0x91a6cf26  <+0102>  test   %eax,%eax
0x91a6cf28  <+0104>  je     0x91a6cf30 <objc_msgSend+112>
0x91a6cf2a  <+0106>  mov    %eax,0x4(%esp)
0x91a6cf2e  <+0110>  jmp    0x91a6ced4 <objc_msgSend+20>
0x91a6cf30  <+0112>  mov    $0x0,%edx
0x91a6cf35  <+0117>  ret    
0x91a6cf36  <+0118>  nopw   %cs:0x0(%eax,%eax,1)

Мой метод cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger section = [indexPath section];
    NSUInteger row = [indexPath row];
    NSString *key = [categories objectAtIndex:section];
    NSArray *nameSection = [categoriesSounds objectForKey:key];
    static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
                             SectionsTableIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc]
                 initWithStyle:UITableViewCellStyleDefault
                 reuseIdentifier:SectionsTableIdentifier] autorelease];
    }
    cell.textLabel.text = [[nameSection objectAtIndex:row] objectAtIndex: 0];

    if (leftSwitch.on == YES){
        NSUInteger leftRow = [leftOldIndexPath row];
        NSUInteger leftSection = [leftOldIndexPath section];
        cell.accessoryType = (row == leftRow && section == leftSection && leftOldIndexPath !=nil) ?
        UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
        }
    if (downSwitch.on == YES){
        NSUInteger downRow = [downOldIndexPath row];
        NSUInteger downSection = [downOldIndexPath section];
        cell.accessoryType = (row == downRow && section == downSection && downOldIndexPath !=nil) ?
        UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
    }
    if (rightSwitch.on == YES){
        NSUInteger rightRow = [rightOldIndexPath row];
        NSUInteger rightSection = [rightOldIndexPath section];
        cell.accessoryType = (row == rightRow && section == rightSection && rightOldIndexPath !=nil) ?
        UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
    }

    return cell;
}

Ответы [ 5 ]

2 голосов
/ 18 января 2010

Анализируя ваш код, я вижу несколько мест, где вы можете потерпеть неудачу.

Прежде всего:

NSMutableString *soundName = [[sound objectAtIndex: row] objectAtIndex: 0];
NSMutableString *soundOfType = [[sound objectAtIndex: row] objectAtIndex: 1];

Есть ли у вас более 25 элементов в массиве звуков?

Второй из всех:

if (indexPath != downOldIndexPath) {

Что такое downOldIndexPath? Вы уверены, что если вы передадите его этому методу

UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:downOldIndexPath];

это правильный путь индекса?

0 голосов
/ 06 февраля 2010

У меня такая же проблема, я вижу, вы решили ее следующим образом:

Спасибо, Эдди, NSZombieEnabled указал мне верное направление, и я смог решить проблему.Выяснилось, что мое значение сохранения пути индекса должно быть увеличено на 1 в cellForRowAtIndexPath.- Джонатан Коэн 25 января в 18: 00

Извините, я немного новичок в программировании для iPhone, что это значит точно?

Я пробовал несколько вещей, и все они, кажется, работают, мне просто интересно, какой путь правильный !?

Я пробовал это:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CheckMarkCellIdentifier = @"CheckMarkCellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CheckMarkCellIdentifier];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc]
                 initWithStyle:UITableViewCellStyleSubtitle
                 reuseIdentifier:CheckMarkCellIdentifier] autorelease];
    }

    // need to retain to stop this crashing with rows > ~26
    [indexPath retain];

    NSUInteger row = [indexPath row];
    NSUInteger oldRow = [lastIndexPath row];

    // Print the text
    cell.textLabel.text = [itemTextList objectAtIndex:row];

    // Print the detail text
    cell.detailTextLabel.text = [itemDetailTextList objectAtIndex:row];

    cell.accessoryType = (row == oldRow && lastIndexPath != nil) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;

    return cell;
}

Также (отдельно) Я пробовал оба из них:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger newRow = [indexPath row];
    NSUInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;

    if (newRow != oldRow) {
        UITableViewCell *newCell = [tableView cellForRowAtIndexPath: indexPath];
        newCell.accessoryType = UITableViewCellAccessoryCheckmark;

        UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];
        oldCell.accessoryType = UITableViewCellAccessoryNone;

        // retain indexPath to use as last index path       
        lastIndexPath = [indexPath retain];
    }

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

и

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger newRow = [indexPath row];
    NSUInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;

    if (newRow != oldRow) {
        UITableViewCell *newCell = [tableView cellForRowAtIndexPath: indexPath];
        newCell.accessoryType = UITableViewCellAccessoryCheckmark;

        UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];
        oldCell.accessoryType = UITableViewCellAccessoryNone;

        // get a copy to use as last index path     
        lastIndexPath = [indexPath copy];
    }

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

Теперь я колеблюсь в направлении последней [indexPath copy], это правильный способ сделать это с точки зрения управления памятью?Или это действительно не имеет значения, сохраняю ли я это или копирую?

Спасибо,

Мэтт.

0 голосов
/ 18 января 2010

Если бы вы обращались к большему количеству элементов, чем удерживаемый массив, вы бы получили исключение вне пределов - не аварийное завершение EX_BAD_ACCESS.

Это означает, что вы пытаетесь получить доступ к освобожденной памяти.Есть две возможности:

1) Элемент, который вы извлекаете из массива, был освобожден.Это маловероятно, так как вам пришлось бы делать дополнительные выпуски, чтобы избавиться от чего-либо, хранящегося в массиве.

2) (скорее всего) Вы выпустили один из массивов, из которых вы пытаетесь получить данные -или, точнее, вы получаете массив откуда-то, а затем забываете его сохранить (поскольку большинство вещей, переданных вам другими методами, автоматически высвобождаются).

0 голосов
/ 18 января 2010

У меня есть 101 строка в моем текущем проекте. Насколько я знаю, нет предела.

Что касается аварии, можете ли вы дать нам больше информации? Как трассировка стека? Консольный вывод?

0 голосов
/ 18 января 2010

При сбое вашего приложения вы видите какие-либо сообщения об ошибках, зарегистрированные в консоли отладчика? (Если он недоступен для просмотра во время отладки приложения, выберите пункт меню «Пуск» -> «Консоль» в XCode). Здесь вы должны увидеть некоторые записи в журнале, которые помогут указать вам правильное направление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...