表视图崩溃与'*** - [__NSArrayM insertObject:atIndex:]:对象不能为零'
Posted
技术标签:
【中文标题】表视图崩溃与\'*** - [__NSArrayM insertObject:atIndex:]:对象不能为零\'【英文标题】:tableview crash with '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'表视图崩溃与'*** - [__NSArrayM insertObject:atIndex:]:对象不能为零' 【发布时间】:2014-06-01 21:09:22 【问题描述】:我遇到了问题。
我的 ViewController 中有一个 TableView。这个 TableView 有 5 行带有 textFields。每行的高度为 156 像素。我也有“保存”按钮,单击后我想通过以下方法将所有数据保存到NSMutableArray
,但结果出现错误。
我该怎么办?
谢谢
我的方法示例:
- (void) saveDataToArray
carCellTableViewCell * cell;
_carNewPrices = [[NSMutableArray alloc] init];
for (int i = 0; i < 5; i++)
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carPrices addObject:cell.priceText.text];
这里是 cellForRowAtIndexPath:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
carCellTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.nameLabel.text = [_carNames objectAtIndex:indexPath.row];
cell.priceLabel.text = [NSString stringWithFormat:@"$%@/day",[_carPrices objectAtIndex:indexPath.row]];
cell.infoLabl.text = [_carInfos objectAtIndex:indexPath.row];
switch (indexPath.row)
case 0:
[cell.img setImage:[UIImage imageNamed:@"rolls.jpg"]];
return cell;
case 1:
[cell.img setImage:[UIImage imageNamed:@"bentley.jpg"]];
return cell;
case 2:
[cell.img setImage:[UIImage imageNamed:@"mercedes.jpg"]];
return cell;
case 3:
[cell.img setImage:[UIImage imageNamed:@"bmw.jpg"]];
return cell;
case 4:
[cell.img setImage:[UIImage imageNamed:@"skoda.jpg"]];
default:
break;
return cell;
补充: 在我的 tableviewCell 中,我有一个标签和一个文本字段。当我点击“保存”时,我想保存 textField 中的所有数据并将其发送到标签。
这是 .m 文件中的所有代码:
#import "carListViewController.h"
#import "carCellTableViewCell.h"
#import "UserSingleton.h"
#import "CheckInternetConnection.h"
#define getCarList @"http:mylink.php" //changed
#define setCarList @"http:mylink.php" //changed
@interface carListViewController ()
@property (weak, nonatomic) IBOutlet UIBarButtonItem *editButtonOutler;
- (IBAction)editButtonOnClick:(id)sender;
@property BOOL editOrSave;//0 when edit, 1 when save
@property UserSingleton * userInfo;
@property NSMutableArray *json;
@property NSMutableArray * carNames;
@property NSMutableArray * carPrices;
@property NSMutableArray * carInfos;
@property NSMutableArray * carNewPrices;
- (void) setData;
@property (weak, nonatomic) IBOutlet UITableView *meTableView;
- (void) saveDataToArray;
- (void) getDataOfCars;
@end
@implementation carListViewController
- (void)viewDidLoad
[super viewDidLoad];
self.title = @"List of cars";
// Do any additional setup after loading the view.
- (void) viewWillAppear:(BOOL)animated
CheckInternetConnection * checkInternet = [[CheckInternetConnection alloc] init];
if (![checkInternet isInternetAvailable])
[self.navigationController popViewControllerAnimated:YES];
_userInfo = [UserSingleton sharedInstance];
if (_userInfo.priority == 2)
_editButtonOutler.enabled = YES;
_editButtonOutler.title = @"Edit";
else
_editButtonOutler.enabled = NO;
_editButtonOutler.title = @"";
_editOrSave = NO;
[self getDataOfCars];
[_meTableView reloadData];
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
return 1;
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return 5;
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
carCellTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.nameLabel.text = [_carNames objectAtIndex:indexPath.row];
cell.priceLabel.text = [NSString stringWithFormat:@"$%@/day",[_carPrices objectAtIndex:indexPath.row]];
cell.infoLabl.text = [_carInfos objectAtIndex:indexPath.row];
switch (indexPath.row)
case 0:
[cell.img setImage:[UIImage imageNamed:@"rolls.jpg"]];
return cell;
case 1:
[cell.img setImage:[UIImage imageNamed:@"bentley.jpg"]];
return cell;
case 2:
[cell.img setImage:[UIImage imageNamed:@"mercedes.jpg"]];
return cell;
case 3:
[cell.img setImage:[UIImage imageNamed:@"bmw.jpg"]];
return cell;
case 4:
[cell.img setImage:[UIImage imageNamed:@"skoda.jpg"]];
default:
break;
return cell;
- (IBAction)editButtonOnClick:(id)sender
if (_editOrSave == 0)
_editOrSave = 1;
_editButtonOutler.title = @"Save";
carCellTableViewCell * cell;
for (int i = 0; i < 5; i ++)
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.priceLabel.hidden = YES;
cell.priceText.hidden = NO;
cell.priceText.text = [[_json objectAtIndex:i] objectForKey:@"cost"];
else if (_editOrSave == 1)
_editOrSave = 0;
carCellTableViewCell * cell;
for (int i = 0; i < 5; i ++)
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.priceLabel.hidden = NO;
cell.priceText.hidden = YES;
[self saveDataToArray];
[self setData];
//cell.priceLabel.text = [_carPrices objectAtIndex:i];
_editButtonOutler.title = @"Edit";
[self getDataOfCars];
[_meTableView reloadData];
- (void) getDataOfCars
_carInfos = [[NSMutableArray alloc] init];
_carNames = [[NSMutableArray alloc] init];
_carPrices = [[NSMutableArray alloc] init];
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:getCarList] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];
_json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
carCellTableViewCell * cell;
for (int i = 0; i < _json.count; i ++)
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carNames addObject:[[_json objectAtIndex:i] objectForKey:@"name"]];
[_carPrices addObject:[[_json objectAtIndex:i] objectForKey:@"cost"]];
[_carInfos addObject:[[_json objectAtIndex:i] objectForKey:@"about"]];
- (void) setData
for (int i = 0; i < 5; i ++)
NSMutableString * postString = [NSMutableString stringWithFormat:setCarList];
[postString appendString:[NSString stringWithFormat:@"?id=%d", i+1]];
[postString appendString:[NSString stringWithFormat:@"&cost=%@", [_carPrices objectAtIndex:i]]];
[postString setString:[postString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:postString]];
[request setHTTPMethod:@"POST"];
NSURLConnection * postConnection;
postConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
- (void) saveDataToArray
carCellTableViewCell * cell;
_carNewPrices = [[NSMutableArray alloc] init];
for (int i = 0; i < 5; i++)
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carPrices addObject:cell.priceText.text];
@end
似乎导致了错误,因为并非所有单元格都在屏幕上可见。在我现在向下滚动之后,即使最后一个单元格在我点击编辑按钮后也发生了变化。
如何解决这个问题?
【问题讨论】:
【参考方案1】:用 UITableView 中的内容填充数组是颠倒的。这样做的方法是相反的。
换句话说,您可以在代码中的其他位置确定 priceText 标签中的内容。如果是静态表,那么信息可能在 IB 中,或者如果您正在实现 tableview:cellForRowAtIndexPath:,那么您正在那里查找 priceText。
将这些值放入 priceArray。
您的修改有帮助。这一行:
[NSString stringWithFormat:@"$%@/day",[_carPrices objectAtIndex:indexPath.row]];
是你的朋友,所以:
NSMutableArray *newArrayOfStrings = [NSMutableArray array];
for (int i=0; i<_carPrices.count; i++)
NSString *str = [NSString stringWithFormat:@"$%@/day",_carPrices[i]];
[newArrayOfStrings addObject:str];
再次编辑。更多代码和 cmets,更清晰:
声明你的vc实现了UITextFieldDelegate,并声明一个属性来保存你编辑的价格:
@interface MyViewController <UITextFieldDelegate>
@property (nonatomic, strong) NSMutableArray *editedStrings;
// initialize this with the carPrices after you get these from JSON
self.editedStrings = [_carPrices mutableCopy]; // if they are NSNumbers
// if they are strings, you'll need a deeper copy:
self.editedStrings = [NSMutableArray array];
for (NSString *str in _carPrices)
[self.editedStrings addObject:[str copy]];
在 cellForRowAtIndexPath 中,让你的 vc 成为委托,并标记 textFields,这样你就知道正在编辑哪个:
cell.priceLabel.delegate = self;
cell.priceLabel.tag = indexPath.row;
然后实现用户编辑时的委托方法:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
NSInteger index = textField.tag;
NSString *candidateString = [textField.text stringByReplacingCharactersInRange:range withString:string];
[self.editedStrings replaceObjectAtIndex:index withObject: candidateString];
return YES;
【讨论】:
我应该只将文本字段中的值写入我的数组,而不是这样:@"$/day"。只有价格。 取决于你想要什么。看起来您已经有了一组价格(这些是数字?还是字符串?)。 stringWithFormat 代码添加货币单位和 /day。你想要数组中的那些东西吗? 我用我在 .m 文件中编写的所有代码更新我的帖子。 我已经有一个数组,因为我从 json 下载数据,编辑后我想把它上传回来 啊。所以这些是单元格中的文本字段,用户编辑它们,你想得到编辑后的文本吗?啊。您仍然需要数组中的字符串。您需要使您的 vc 成为文本字段的代表,并且当它们应该更改字符范围时,您需要更新数组中的字符串。那么到了上传的时候,这个数组就不需要做任何工作了。【参考方案2】:在[_carPrices addObject:cell.priceText.text]
行添加断点,您会看到在某个索引处,文本将为nil。我无法告诉你为什么它会为零,因为我不知道你是如何创建单元格的。
【讨论】:
我已将 cellForRowAtIndexPath 添加到我的问题中以上是关于表视图崩溃与'*** - [__NSArrayM insertObject:atIndex:]:对象不能为零'的主要内容,如果未能解决你的问题,请参考以下文章
我们可以通过使用@try,catch 机制来防止崩溃吗?如果错误是 -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty arra
[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 1]
领域:获取 -[__NSArrayM UTF8String]:无法识别的选择器发送到实例
Facebook JSON 提要 - __NSArrayM insertObject:atIndex:]:对象不能为 nil
-[__NSArrayM objectAtIndex:]:索引 0 超出了带有 userInfo 的空数组的界限(null)