пустой nsarray вылетает uitableview - PullRequest
0 голосов
/ 16 сентября 2011

Я перехватываю кучу данных с моего сервера, затем анализирую их, затем передаю эти проанализированные данные методу, который сортирует мой массив по алфавиту. Все это работает, но мое табличное представление отображается до того, как у меня появятся какие-либомассив, так что мое приложение падает ... как я могу предотвратить это?

//...
tableView:cellForRowAtIndexPath:
//..
//configure cell
[[cell textLabel] setText:[sortedArray objectAtIndex:[indexPath row]]]; // this is where I am passing the data into each cell
///

//parsing stuff happens here then I passed the parsed data over to my sorting method...


//method to sort array and split for use with uitableview Index
- (IBAction)startSortingTheArray:(NSMutableArray *)arrayData
{
    //Sort incoming array alphabetically
    sortedArray = [arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

    //Reloads data in table
    [self.tableView reloadData];
}

ошибка msg

2011-09-16 15:04:06.096 Code[8630:207] -[UILabel objectAtIndex:]: unrecognized selector sent to instance 0x4c767e0
2011-09-16 15:04:06.099 Code[8630:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILabel objectAtIndex:]: unrecognized selector sent to instance 0x4c767e0'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x010da5a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x0122e313 objc_exception_throw + 44
    2   CoreFoundation                      0x010dc0bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x0104b966 ___forwarding___ + 966
    4   CoreFoundation                      0x0104b522 _CF_forwarding_prep_0 + 50
    5   Code                           0x0003d225 -[VehicleResultViewController tableView:cellForRowAtIndexPath:] + 405
    6   UIKit                               0x0063bb98 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 634
    7   UIKit                               0x006314cc -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
    8   UIKit                               0x006468cc -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1561
    9   UIKit                               0x0063e90c -[UITableView layoutSubviews] + 242
    10  QuartzCore                          0x01ee0a5a -[CALayer layoutSublayers] + 181
    11  QuartzCore                          0x01ee2ddc CALayerLayoutIfNeeded + 220
    12  QuartzCore                          0x01e880b4 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 310
    13  QuartzCore                          0x01e89294 _ZN2CA11Transaction6commitEv + 292
    14  QuartzCore                          0x01e8946d _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 99
    15  CoreFoundation                      0x010bb89b __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
    16  CoreFoundation                      0x010506e7 __CFRunLoopDoObservers + 295
    17  CoreFoundation                      0x010191d7 __CFRunLoopRun + 1575
    18  CoreFoundation                      0x01018840 CFRunLoopRunSpecific + 208
    19  CoreFoundation                      0x01018761 CFRunLoopRunInMode + 97
    20  GraphicsServices                    0x018971c4 GSEventRunModal + 217
    21  GraphicsServices                    0x01897289 GSEventRun + 115
    22  UIKit                               0x005d4c93 UIApplicationMain + 1160
    23  Code                           0x00002609 main + 121
    24  Code                           0x00002585 start + 53
)
terminate called after throwing an instance of 'NSException'

ОБНОВЛЕНО // инициализация массива в 0 внутри viewdidload теперьвыдает мне ошибку «EXC_BAD_ACCESS»

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.sortedArray = [NSArray alloc];
}

Ответы [ 7 ]

3 голосов
/ 16 сентября 2011

Похоже, что sortedArray равно nil или имеет счет сохранения нуля, и это сбивает с толку отладчик в отношении его класса. Я видел это в своем собственном коде, когда позволил этому случиться: ваша проблема связана с использованием = без self в поле зрения, и поэтому вы, вероятно, создаете зомби. В случае сомнений запустите Анализатор в «Продукт -> Анализ» (XCode 4. *).

Чтобы исправить проблему, вам нужно использовать синтезированные геттеры и сеттеры. В вашем интерфейсе я рекомендую объявить что-то вроде:

@property(retain) NSArray * sortedArray;

и кое-где в вашей реализации:

@synthesize sortedArray;

Тогда вместо sortedArray = [arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];, что плохо, поскольку он обходит все удержания, выполните:

[self setSortedArray:[arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]]; или

self.sortedArray = [arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

Они эквивалентны. Хотя = появляется во втором варианте, компилятор распознает это как вызов установщика, правильно управляя счетом сохранения.

Наконец, в методе dealloc вашего подкласса вы должны освободить sortedArray перед вызовом dealloc для super, иначе у вас будет утечка памяти.

В общем, я бы покончил с ivar s как можно больше, за исключением управления каким-то внутренним состоянием для вашего пользовательского объекта, который должен быть закрытым. Если по умолчанию вы звоните, скажем, [self myMember] или [self setMyMember:], вы дисциплинируете себя и избавите себя от стресса, вызванного этой ошибкой.

Если вы чувствуете себя особенно уверенно, лично я бы переопределил установщик для вашего массива с помощью чего-то вроде:

- (void) setSortedArray:(NSArray *) anArray
{
  // Make this thread safe by surrounding with a lock.
  @synchronized(self)
  {
    // Always retain the new before releasing the old, in
    // case the old and new are the same object!
    [anArray retain]
    [self.sortedArray release];

    // Set the data array; we don't call on self here.
    sortedArray = anArray;

    // UIKit is not thread safe so we push the reload
    // call onto the main thread; blocks only work in
    // iOS4.1 and up, otherwise perform selector in
    // the background:
    // [self.tableView performSelectorInBackground:@selector(reloadData) withObject:nil];

    dispatch_async(dispatch_get_main_queue(), ^{
      // Update the table
      [self.tableView reloadData];
    }];
  }
}

Также объявите собственность с

@property(nonatomic, assign, setter = setSortedArray:) NSArray * sortedArray;

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

Примечание. Я не тестировал приведенный выше код, я написал его в коробке SO.

1 голос
/ 16 сентября 2011

Также обратите внимание, что в сообщении об ошибке говорится, что UILabel не распознает msg objectAtIndex:

Я предполагаю, что sortedArray неинициализирован и просто является оставшейся UILabel.(Особенно, если вы покажете, что он устанавливается позже).

Если вы намереваетесь использовать sortedArray, сделайте его свойством и всегда называйте его как self.sortedArray (чтобы он был инициализирован и правильноудержанного / отпущена).

0 голосов
/ 16 сентября 2011
- (IBAction)startSortingTheArray:(NSMutableArray *)arrayData
{
    //Sort incoming array alphabetically
    sortedArray = [arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

    //Reloads data in table
    [self.tableView reloadData];
}
[arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; 

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

0 голосов
/ 16 сентября 2011

Изменить это:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.sortedArray = [NSArray alloc];
}

К этому:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.sortedArray = [NSArray array];
}
0 голосов
/ 16 сентября 2011

Вы должны передать 0 в

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{

}

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

-> Инициализировать sortedArray (без объектов в нем) перед загрузкой табличного представления, возможно, в viewDidLoad

self.sortedArray = [NSMutableArray array];

-> И вернуть счетчик массива в numberOfRows

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    {
      return [self.sortedArray count];
    }

-> Перезагрузить таблицу после завершения добавления данных в массив

//Make sure you call this when there is some data in the sorted array
[self.tableView reloadData];
0 голосов
/ 16 сентября 2011

Ваш журнал ошибок показывает, что вы отправляете сообщение objectAtIndex в UILabel.Это вызывает аварию.По крайней мере, эта строка не вызывает objectAtIndex для метки ячейки:

[[cell textLabel] setText:[sortedArray objectAtIndex:[indexPath row]]];

Есть ли где-нибудь еще, если ваш код, который вы вызываете objectAtIndex?Нажмите Ctrl + F и найдите «objectAtIndex» в вашем контроллере представления. M

0 голосов
/ 16 сентября 2011

Независимо от того, является ли он UITableViewController или UITableView внутри другого контроллера представления, сначала установите источник данных так, как вы хотите, а затем продолжайте. Если это UITableViewController, я бы предложил переопределить метод init и передать ему отсортированный массив в качестве дополнительного аргумента. В противном случае, если это UITableView в другом контроллере представления, отсортируйте массив и только затем создайте объект UITableView и добавьте его в качестве подпредставления.

EDIT: И, как говорит xuzhe ниже, ваш отсортированный массив вообще является объектом массива?

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