我有一个UITableView,总共有8个单元格(部分),其中6个包含textFields作为子视图,2个包含按钮,另一个包含文本视图。现在我遇到了一个问题,因为我们都是意识到只有视图出现时,可见单元格才会加载。所以当我的应用程序加载时,我能够查看5个单元格,前4个包含文本字段,第5个单元格带按钮。我可以看到数组计数是4当我通过登录控制台显示它,即
there are 4 objects in the array
现在滚动表格视图后,我可以观察到以下内容:
there are 6 objects in the array
所以,正在发生的事情是如果我要保存在表视图中输入的数据,或者说编辑以更改现有数据,我被迫滚动表视图并在最后一个单元格中输入值。所以不能总是与用户的情况,因为我们不能指望他/她滚动表视图并输入完整的表格/表格视图单元格条目。他/她做什么改变他们将只需点击完成/保存什么它是......!
更多我有一个选择器视图作为包含文本字段的最后一个单元格的输入视图作为subview.Hence在我的选择器视图中确实选择了行方法我面临着包含选择器的最后一个单元格/部分(textField作为子视图)的崩溃问题这里查看我的方法代码片段:
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch (tagValues)
{
case 105:
{
self.textField = [self.fields objectAtIndex:3];
self.textField.text = [self.reminder objectAtIndex:row];
}
break;
case 107:
{
//Crash occurring in this case,sometimes its working wonder why
self.textField = [self.fields objectAtIndex:5];
self.textField.text = [self.group objectAtIndex:row];
}
break;
}
}
**Note**:I am using the same textField for adding as subview to all 6 cells,but each one with unique tags and own purpose,i.e. one for editing text using key board,one with date picker,one with general picker etc...
我想知道为什么有一些时候从选择器视图中选择值(最后一个单元格)会崩溃一些时间并且有些时候工作正常。有时候它会在 case 107 中评论的上面一行崩溃,有时候在主自动释放池中。一些时间线程如下面的快照所示:
那么有什么方法可以一次加载所有单元格,以便在滚动之前将所有文本字段添加到数组中。我相信不会有任何问题
更详细的编辑码以便理解:
- (UITableViewCell *)tableView:(UITableView *)atableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSString *identifier = @"UITableViewCell";
NSString *cellIdentifierF = nil;
static NSString *firstCellIdentifier = @"FirstCell";
static NSString *secondCellIdentifier = @"SecondCell";
static NSString *thirdCellIdentifier = @"ThirdCell";
static NSString *fourthCellIdentifier = @"FourthCell";
static NSString *fifthCellIdentifier = @"FifthCell";
static NSString *sixthCellIdentifier = @"SixthCell";
static NSString *seventhCellIdentifier = @"SeventhCell";
static NSString *eightCellIdentifier = @"EightCell";
if(indexPath.section == 0 && indexPath.row == 0)
{
cellIdentifierF = firstCellIdentifier;
}
else if(indexPath.section == 1 && indexPath.row == 0)
{
cellIdentifierF = secondCellIdentifier;
}
else if(indexPath.section == 2 && indexPath.row == 0)
{
cellIdentifierF = thirdCellIdentifier;
}
else if(indexPath.section == 3 && indexPath.row == 0)
{
cellIdentifierF = fourthCellIdentifier;
}
else if(indexPath.section == 4 && indexPath.row == 0)
{
cellIdentifierF = fifthCellIdentifier;
}
else if(indexPath.section == 5 && indexPath.row == 0)
{
cellIdentifierF = sixthCellIdentifier;
}
else if(indexPath.section == 6 && indexPath.row == 0)
{
cellIdentifierF = seventhCellIdentifier;
}
else if(indexPath.section == 7 && indexPath.row == 0)
{
cellIdentifierF = eightCellIdentifier;
}
UITableViewCell *cell = (UITableViewCell *)[atableView dequeueReusableCellWithIdentifier:cellIdentifierF];
atableView.backgroundColor = [UIColor clearColor];
textField = [[[UITextField alloc]initWithFrame:CGRectMake(15, 12, 300, 24)]autorelease];
textField.textColor = [UIColor whiteColor];
textField.delegate = self;
tagValues = textField.tag;
switch (indexPath.section)
{
case 0:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: firstCellIdentifier])
{
textField.placeholder = @"Enter name";
[self.textField setValue:[UIColor purpleColor]
forKeyPath:@"_placeholderLabel.textColor"];
textField.tag = 101;
textField.text = reminderInstance.Name;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
NSLog(@"Value = %@",textField.text);
[cell.contentView addSubview:textField];
[self.fields addObject:textField];
}
}
}
break;
case 1:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: secondCellIdentifier])
{
textField.tag = 102;
textField.text = reminderInstance.Event;
NSLog(@"Value = %@",textField.text);
[cell.contentView addSubview:textField];
[self.fields addObject:textField];
}
}
}
break;
case 2:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: thirdCellIdentifier])
{
textField.placeholder = @"Click here to set date and time";
[self.textField setValue:[UIColor purpleColor]
forKeyPath:@"_placeholderLabel.textColor"];
textField.inputView = self.datePicker;
textField.text = reminderInstance.Date;
textField.tag = 103;
NSLog(@"Value = %@",textField.text);
[cell.contentView addSubview:textField];
[self.fields addObject:textField];
}
}
}
break;
case 3:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: fourthCellIdentifier])
{
textField.tag = 105;
textField.text = reminderInstance.numDays;
textField.inputView = self.reminderPicker;
NSLog(@"Value = %@",textField.text);
[cell.contentView addSubview:textField];
[self.fields addObject:textField];
}
}
}
break;
case 4:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: fifthCellIdentifier])
{
checkboxButton = [[[UIButton alloc] initWithFrame:CGRectMake(16,1,120, 44)]autorelease];
[checkboxButton setImage:[UIImage imageNamed:@"ewee.png"] forState:UIControlStateNormal];
[checkboxButton addTarget:self action:@selector(toggleButton:) forControlEvents:UIControlEventTouchUpInside];
NSString *one = reminderInstance.selString;
NSNumber* i = [NSNumber numberWithInt:[one intValue]];
BOOL isOn = [i boolValue];
if(isOn)
{
[checkboxButton setImage:[UIImage imageNamed:@"checkarrow.png"] forState:UIControlStateNormal];
}
else
{
[checkboxButton setImage:[UIImage imageNamed:@"ewee.png"] forState:UIControlStateNormal];
}
NSLog(@"String Val = %@",one);
[checkboxButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[checkboxButton setImageEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)];
[cell addSubview:checkboxButton];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(55, 10, 225, 24)];
label.text = @"Every Year";
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor clearColor];
[cell addSubview:label];
cell.textLabel.textColor = [UIColor whiteColor];
[label release];
}
}
}
break;
case 5:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: sixthCellIdentifier])
{
textField.placeholder = @"Enter the number here";
[self.textField setValue:[UIColor purpleColor]
forKeyPath:@"_placeholderLabel.textColor"];
textField.text = num;
textField.text = reminderInstance.number;
textField.tag = 106;
textField.userInteractionEnabled = YES;
textField.keyboardType = UIKeyboardTypeNumberPad;
NSLog(@"Value = %@",textField.text);
[cell.contentView addSubview:textField];
[self.fields addObject:textField];
}
}
}
break;
case 6:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"reminderbuttonxl.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: seventhCellIdentifier])
{
cell.backgroundColor = [UIColor clearColor];
textView.clipsToBounds = YES;
textView = [[UITextView alloc]initWithFrame: CGRectMake(-2, -3, 307, 154)];
UIImageView *imgView = [[[UIImageView alloc]initWithFrame: textView.frame]autorelease];
imgView.image = [UIImage imageNamed: @"buttonbg_text.png"];
[textView addSubview: imgView];
[textView sendSubviewToBack: imgView];
textView.backgroundColor = [UIColor clearColor];
textView.delegate = self;
textView.tag = 11;
tagValues = textView.tag;
textView.textColor = [UIColor purpleColor];
[cell.contentView addSubview:textView];
textView.text = @"Your birthday wishes/other reminder body here";
NSLog(@"Value = %@",textView.text);
}
}
}
break;
case 7:
{
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
//Only add content to cell if it is new
if([cellIdentifierF isEqualToString: eightCellIdentifier])
{
textField.tag = 107;
textField.inputView = self.groupPicker;
tagValues = textField.tag;
textField.text = reminderInstance.remGroup;
NSLog(@"Value = %@",textField.text);
[cell.contentView addSubview:textField];
[self.fields addObject:textField];
}
}
}
break;
default:
break;
}
int size = [fields count];
NSLog(@"there are %d objects in the array", size);
return cell;
}
我已经多次尝试找出究竟出了什么问题,我还检查了一些问题here和there。但是找不到任何有效/ appr。回答或解决了我的问题。
所以任何人都应该帮助我提供有价值的建议或示例代码段。
提前感谢所有人:)
答案 0 :(得分:4)
从您构建表单的方式(实际上是这种情况)中会出现很多问题是有道理的 当我需要构建一个这样的表单时,我自己一直在做的是使用所有控件构建一个普通视图,无论它有多长,并在滚动视图中使用该表单并使用视图的大小设置其内容大小在里面。这将让您更好地控制您希望该表单的外观。 而且我认为我没有看过使用tableview进行表单输入的应用程序。
您可以使用界面构建器来构建表单(只需欺骗Xcode并使主视图和滚动视图足够大,以便您可以在构建器上看到所有内容,然后在完成后将其调整为适当的大小)< / p>
答案 1 :(得分:1)
听起来你可能最好不要使用表视图,而是使用滚动视图。如果你确实有一些固定数量的东西要显示,你可以将它们放在滚动视图上作为视图(而不是表格单元格),你的代码将变得更加简单。
如果您想要从表格视图中获得的只是外观,您可以简单地使用看起来像您想要的背景图像,并在该背景上叠加视图和控件。您应该能够在Interface Builder中完成所有这些操作。
如果采用这种方法,视图控制器中的代码现在就是处理文本输入和按钮按钮所需的代码,您无需担心表视图委托或数据源。
答案 2 :(得分:1)
虽然这似乎已经解决了,但是作为“肮脏的黑客”可能做的是在执行任何操作之前使整个表滚动到底部。像 [myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
这样的东西,这将被迫加载所有的UITableCellView。请记住,这不是首选方式,但可以在需要最小代码更改时使用。
答案 3 :(得分:0)
UITableView仅加载可见单元格,并且一直滚动UITableView,调用回调cellForRowAtIndexPath:
。但让我直截了当。为什么需要UITableView来制作表单?正如我所看到的,你每个部分加载一个单元格...而且,你只是初始化单元格。你应该做什么子类UITableViewCell并在那里创建你的对象。
然后这样打电话:
cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
然后你可以准确地调用你想要的控制器。并且您必须在滚动时控制UITableView的行为。像这样:
case 7:
{
if (cell == nil)
{
cell = [[[MyCustomCellEigth alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifierF] autorelease];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"buttonbg-1.png"]];
/*this should be done in the Custom Cell init method
if([cellIdentifierF isEqualToString: eightCellIdentifier])
{
textField.tag = 107;
textField.inputView = self.groupPicker;
tagValues = textField.tag;
textField.text = reminderInstance.remGroup;
NSLog(@"Value = %@",textField.text);
[cell.contentView addSubview:textField];
[self.fields addObject:textField];
}
*/
}
else
{
//Control content
((MyCustomCell*)cell).myTextField.text = @"SOME TEXT";
}
}
break;
关于选择器。它可能仅在您滚动所有表后才起作用,因为它引用了一个textField,只有在对应的单元格可见时才会将其添加到Array中。
没有更多事情要做。但是按照这个,你应该没事。首先,子类UITableViewCell。您可以通过编程方式或使用xib自行创建控件。这将使您更好地控制单元格本身。关于选择器,不是使用控件创建数组,而是使用它应具有的值创建它。有人输入内容后,使用UITextFieldDelegate保存。 希望它有所帮助。
编辑:
您必须创建UITableViewCell的子类。在Xcode上,创建一个新文件。选择objective-c Class。在下一个屏幕上,在字段子类中,选择UITableViewCell并相应地命名您的单元格。这将创建一个将覆盖initWithStyle:reuseIdentifier:
方法的类。在这个方法中,你应该把你的初始代码。
#import <UIKit/UIKit.h>
@interface MyCustomCellOne : UITableViewCell
{
UITextField *textField;
}
@end
#import "MyCustomCellOne.h"
@implementation MyCustomCellOne
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
textField = [[UITextField alloc] initWithFrame:"YOUR FRAME"];
textField.tag = 107;
textField.text = @"SOME TEXT";
[self addSubview:textField];
}
return self;
}