我有一个带有动态单元格的tableView。每个部分有5行。在每行的前4行中有一个文本字段。相反,在第五行有一个imageview(当我点击这一行时,我可以从我的照片库中选择一张照片,最后一张将被放入imageView)。使用步进器在运行时决定部分的数量。第0部分是固定的,包含一个步进器。当我点击+按钮(在步进器上)时,将添加一个部分。所以一切都是正确的,但如果我之前在包含文本字段的行中写入,然后添加一个或多个部分,这些文本字段的内容将相互混合(以及部分之间)。
//In file.h I've declared @property (nonatomic) int numberOfComponents;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1 + self.numberOfComponents;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
return 1;
}
else{
return 4;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
NSString *CellIdentifier = @"cellStepper";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UILabel *stepperLabel = (UILabel *)[cell viewWithTag:1];
stepperLabel.text = [NSString stringWithFormat:@"%i",self.numberOfComponents];
UIStepper *stepper = (UIStepper *)[cell viewWithTag:2];
stepper.minimumValue = 0;
stepper.maximumValue = 20;
stepper.stepValue = 1;
stepper.autorepeat = YES;
stepper.continuous = YES;
return cell;
}
if (indexPath.row == 4) {
NSString *CellIdentifier = @"cellProfileSnap";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
NSString *CellIdentifier = @"cellDetail";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UITextField *cellLabelComponent = (UITextField *)[cell viewWithTag:3];
cellLabelComponent.placeholder = @"detail";
return cell;
}
- (IBAction)stepperClik:(UIStepper *)stepper{
if (stepper.value == 0 && self.numberOfComponents == 0) {
if (stepper.value > self.numberOfComponents) {
self.numberOfComponents += 1;
}
else{
return;
}
}
if (stepper.value > self.numberOfComponents) {
self.numberOfComponents += 1;
}
else{
self.numberOfComponents -= 1;
}
[self.tableView reloadData];
}
由Greg解决,但现在还有另一个问题:我有一个保存按钮,它应该将许多数组保存到字典中(包含每个部分5的详细信息)作为部分的数量。 这里是保存按钮的代码:
- (IBAction)saveButton:(id)sender{
NSMutableArray *arrComponents = [[NSMutableArray alloc] init];
for (int i = 0; i < self.numberOfComponents; i++)
{
NSMutableArray *component = [[NSMutableArray alloc] init];
for (int j = 0; j < [self.arrDetails count]; j++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:j inSection:i+1];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath: indexPath];
if (j == 4){
UIImageView *imageComponent = (UIImageView *) [cell viewWithTag:4];
NSLog(@"%@",imageComponent.image);
if (imageComponent.image == Nil) {
[component addObject: nil];
}
[component addObject: imageComponent.image];
}
else{
UITextField *detailComponent = (UITextField *) [cell viewWithTag:3];
NSLog(@"%@",detailComponent.text);
if ([detailComponent.text isEqualToString:@""]) {
[component addObject:@""];
}
if (detailComponent.text != nil && i != 0)
[component addObject: detailComponent.text];
}
}
[arrComponents addObject: component];
NSLog(@"%@",arrComponents);
}
在代码中显示它/ / ERROR HERE,在最近一次迭代(最后一节读取)的第5次迭代(部分中的行数)的第四次迭代中,应用程序崩溃,给出了这条消息:
由于未捕获的异常而终止应用 'NSInvalidArgumentException',原因:'*** - [__ NSArrayM insertObject:atIndex:]:object不能为nil'
答案 0 :(得分:1)
之所以发生这种情况,是因为您没有保存cellLabelComponent.text属性,并且当您重新加载Data tableView时会重用单元格(这会导致此问题)。 您应该将输入的数据保存到cellLabelComponent(例如,在数组中,您可以使用UITextFieldDelegate),并在您的cellForRowAtIndexPath:方法中将保存的值保存到所需的字段。
// EXTENDED
符合.h文件或类扩展中的<UITextFieldDelegate>
协议。
添加
@property (nonatomic, strong) NSMutableDictionary *textValueDictionary;
到您的类扩展,并在viewDidLoad或init方法中分配它和init:
self.textValueDictionary = [[NSMutableDictionary alloc] init];
将其添加到cellForRowArIndexPath:
cellLabelComponent.placeholder = @"detail";
// Make your class to be delegate for UITextField
cellLabelComponent.delegate = self;
// I use NSString (section) as a key in my dictionary. You can use NSNumber if you like
if (self.textValueDictionary[[NSString stringWithFormat:@"%d", indexPath.section]])
cellLabelComponent.text = self.textValueDictionary[[NSString stringWithFormat:@"%d", indexPath.section]];
else
cellLabelComponent.text = @""; //Your default value
添加您的UITextFieldDelegate方法:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
// Get reference to the cell
UITableViewCell *cell = (UITableViewCell*)[[[textField superview] superview] superview];
// Get index path
NSIndexPath *indexPath = [self.myTableView indexPathForCell:cell];
// Get section as a string
NSString *section = [NSString stringWithFormat:@"%d", indexPath.section];
[self.textValueDictionary setValue:textField.text forKey:section];
}
如果需要,您可以使用更多委托。 它应该足以使它工作。它只会在你的表部分中有一个UITextField时工作,如果你有更多你应该在你的字典中使用唯一键(如果你在部分中有更多的那个文本字段,但NSindexPath将工作,但只记得转换,它将起作用)它到NSNumber)。 让我知道它是否有效。
// EXTENDED
如果每个部分有更多的UITextField,则必须更改字典键。只要每个部分最多有一行,上面的解决方案就可以正常工作。
如果每个部分有多个文本字段但每个单元格不超过一个文本字段(这也适用于每个部分的一个文本字段),则此解决方案(如下所示)将起作用: 从:
更改cellForRowAtIndexPath中的行if (self.textValueDictionary[[NSString stringWithFormat:@"%d", indexPath.section]])
cellLabelComponent.text = self.textValueDictionary[[NSString stringWithFormat:@"%d", indexPath.section]];
为:
NSString *key = [NSString stringWithFormat:@"sec:%d,row:%d", indexPath.section, indexPath.row];
if (self.textValueDictionary[key])
cellLabelComponent.text = self.textValueDictionary[key];
并更改textFieldDidEndEditing:方法中的行:
NSString *section = [NSString stringWithFormat:@"%d", indexPath.section];
[self.textValueDictionary setValue:textField.text forKey:section];
为:
NSString *key = [NSString stringWithFormat:@"sec:%d,row:%d", indexPath.section, indexPath.row];
[self.textValueDictionary setValue:textField.text forKey:key];
答案 1 :(得分:1)
我相信你的detailComponent等于nil,你不能将nil保存到数组中。在你打电话之前
[component addObject: detailComponent.text]; //ERROR HERE
做检查:
if (detailComponent != nil && i != 0)
[component addObject: detailComponent.text];
可能会发生这种情况,因为在您的第0部分中您没有任何文本字段。
// EDITED
这个问题发生在这里:
if (imageComponent.image == Nil) {
[component addObject: nil];
}
[component addObject: imageComponent.image];
将其替换为:
if (imageComponent.image == nil) {
[component addObject:[NSNull null]];
}
else {
[component addObject: imageComponent.image];
}
如果要添加nil,则无法将nil添加到数组中,您应该添加对象NSNull。 你错过了其他声明。您的代码尝试在if语句中首次将nil添加到数组中两次(如果图像为nil)([component addObject:nil];),并在if语句之后第二次:[component addObject:imageComponent.image];
// EDITED
按照以下代码中的评论建议进行更改。我使用相同的字典,您应该更改名称,因为它表明它只保留textfields值,但现在它也将存储图像:
if (indexPath.row == 4) {
NSString *CellIdentifier = @"cellProfileSnap";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//I believe this is where you keep your imageView
// get your image
UIImageView *imageComponent = (UIImageView *) [cell viewWithTag:4];
NSString *key = [NSString stringWithFormat:@"sec:%d,row:%d", indexPath.section, indexPath.row];
if (self.textValueDictionary[key])
imageComponent.image = self.textValueDictionary[key];
else
imageComponent.image = nil; //Your default value (probably you want to set up your plus image)
return cell;
}
您需要做的下一步是用户按下加号图像 - 您必须将图像保存在字典中。将此代码放在您从用户处获取图像的方法中。这是一个伪代码,所以你必须稍微调整一下:
// Get reference to the cell
UITableViewCell *cell = //have a look on textFieldDidEndEditing method. You have to work out how to get the cell (I cannot do that because I haven't got access to your code);
// Get index path
NSIndexPath *indexPath = [self.myTableView indexPathForCell:cell];
// Get section as a string
NSString *key = [NSString stringWithFormat:@"sec:%d,row:%d", indexPath.section, indexPath.row];
UIImage *img = //get your image here;
//make sure it's not nil before you save it to dictionary
//save it to dictionary
[self.textValueDictionary setValue:img forKey:key];
最后一位是saveButton:我昨天的建议中有错误的方法。您正试图直接从单元格获取文本和图像,如果单元格可见,它可以正常工作。如果你看不到细胞系统把它放到可重复使用的池中,你会得到nils。 要修复它,你必须从字典中获取数据: 不要使用:
UIImageView *imageComponent = (UIImageView *) [cell viewWithTag:4];
代替:
NSString *key = [NSString stringWithFormat:@"sec:%d,row:%d", indexPath.section, indexPath.row];
UIImage *img = self.textValueDictionary[key];
// make sure is not nil before you save it. If it's nil add [NSNull nil] to your array as I explained before.
当你阅读文字时,不要这样做:
UITextField *detailComponent = (UITextField *) [cell viewWithTag:3];
从字典中获取文字:
NSString *key = [NSString stringWithFormat:@"sec:%d,row:%d", indexPath.section, indexPath.row];
NSString *str = self.textValueDictionary[key];
如果它抱怨数据类型使用cast(UIImage *)。 请记住将您的第一个循环更改为:for(int i = 1; i&lt; self.numberOfComponents; i ++),当您获得NSIndexPath时,将其更改为inSection:i而不是inSection:i + 1。 我没有在Xcode中运行它,所以可能有一些错误,但你应该能够找到并修复它。 希望它对你有用。