我正从我的服务器捕获一堆数据然后解析它,然后我将这个解析的数据传递给一个按字母顺序对我的数组进行排序的方法..所有这些都有效但我的tableview在我有任何数据之前显示数组,所以我的应用程序正在崩溃...我怎么能阻止这种情况发生?
//...
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];
}
错误消息
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'
UPdATED //在viewdidload中初始化数组为0现在给我一个“EXC_BAD_ACCESS”错误
- (void)viewDidLoad
{
[super viewDidLoad];
self.sortedArray = [NSArray alloc];
}
答案 0 :(得分:3)
看起来sortedArray
是nil
或保留计数为零,这使得调试器与其类相混淆。当我允许这种情况发生时,我已经在我自己的代码中看到了这一点:你的问题源于使用=
而没有self
,因此你可能正在创建一个僵尸。如有疑问,请在“产品” - >中运行分析器。分析'(XCode 4。*)。
要解决此问题,您需要使用合成的getter和setter。在您的界面中,我建议声明一些类似的东西:
@property(retain) NSArray * sortedArray;
以及实施中的一些内容:
@synthesize sortedArray;
然后,代替sortedArray = [arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
,因为它绕过了所有保留,这是不好的,请执行:
[self setSortedArray:[arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]];
或
self.sortedArray = [arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
他们是等同的。虽然第二个选项中出现=
,但编译器会将此识别为setter调用,正确管理保留计数。
最后,在子类的dealloc
方法中,必须在sortedArray
上调用dealloc
之前释放super
,否则会导致内存泄漏。
一般情况下,我会尽可能地删除ivar
,除了管理应该是私有的自定义对象的某种内部状态。如果默认情况下你打电话给[self myMember]
或[self setMyMember:]
,你就会自我约束并避免犯这种错误的压力。
如果您感到特别自信,我个人会用以下内容覆盖您阵列的setter:
- (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
,因为编译器不能保证您的自定义setter是线程安全的。 (相反,我们确保它的线程安全。)无论如何你仍然可以编译,但编译器会警告你这个。
NB。我没有测试过上面的代码,我在SO的框中写了它。
答案 1 :(得分:1)
另请注意,错误消息显示UILabel无法识别msg objectAtIndex:
我猜测sortedArray是未初始化的,恰好是剩下的UILabel。 (特别是当你显示它稍后设定时)。
如果您打算使用sortedArray,请将其作为属性,并始终将其称为self.sortedArray(因此它将被初始化,并正确保留/释放)。
答案 2 :(得分:0)
无论是UITableViewController还是其他视图控制器内的UITableView,首先按照您希望的方式设置数据源,然后继续。如果它是一个UITableViewController,我的建议是覆盖init方法并将有序数组作为额外参数传递给它。否则,如果它是另一个视图控制器中的UITableView,则对数组进行排序,然后创建UITableView对象并将其添加为子视图。
编辑: 正如xuzhe在下面所说,你的排序数组首先是一个数组对象吗?
答案 3 :(得分:0)
您的错误日志显示您正在将objectAtIndex消息发送到UILabel。这导致了崩溃。至少这一行没有在单元格标签上调用objectAtIndex:
[[cell textLabel] setText:[sortedArray objectAtIndex:[indexPath row]]];
如果您的代码正在调用objectAtIndex,还有其他地方吗?按Ctrl + F并在视图controller.m
中搜索“objectAtIndex”答案 4 :(得分:0)
你必须在
中传递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];
答案 5 :(得分:0)
改变这个:
- (void)viewDidLoad
{
[super viewDidLoad];
self.sortedArray = [NSArray alloc];
}
对此:
- (void)viewDidLoad
{
[super viewDidLoad];
self.sortedArray = [NSArray array];
}
答案 6 :(得分:-1)
- (IBAction)startSortingTheArray:(NSMutableArray *)arrayData
{
//Sort incoming array alphabetically
sortedArray = [arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
//Reloads data in table
[self.tableView reloadData];
}
[arrayData sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
返回自动释放的数组。所以不能进一步使用。所以通过保留或复制或分配从该数组获得所有权。然后你的问题将解决