Reputation: 485
I have a UITableViewController that I'm using for a form. Each cell has a UILabel and a UITextField. When I tap on a UITextField, the keyboard comes up, then I scroll down and the cell goes off screen, when I tap on another UITextField, the app crashes.
This is my cell subclass.
@implementation EditorFieldCell
- (id)init
{
self = [super init];
if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:self.textField];
}
return self;
}
- (void)setName:(NSString *)name
{
_name = name;
CGRect frame = self.nameLabel.frame;
frame.size.width = roundf([_name sizeWithFont:[UIFont boldSystemFontOfSize:17.0f]].width);
self.nameLabel.frame = frame;
frame = self.textField.frame;
frame.size.width = self.frame.size.width - 16.0f - 14.0f - 14.0f - self.nameLabel.frame.size.width;
frame.origin.x = 16.0f + 14.0f + self.nameLabel.frame.size.width;
self.textField.frame = frame;
self.nameLabel.text = _name;
}
- (void)setPlaceholder:(NSString *)placeholder
{
_placeholder = placeholder;
self.textField.placeholder = placeholder;
}
- (void)setText:(NSString *)text
{
_text = text;
self.textField.text = text;
}
- (UILabel*)nameLabel
{
if (_nameLabel)
{
return _nameLabel;
}
_nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(16.0f, 0.0f, 0.0f, self.frame.size.height)];
_nameLabel.font = [UIFont boldSystemFontOfSize:17.0f];
return _nameLabel;
}
- (UITextField*)textField
{
if (_textField)
{
return _textField;
}
_textField = [[UITextField alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, self.frame.size.height)];
_textField.font = [UIFont systemFontOfSize:17.0f];
_textField.textAlignment = NSTextAlignmentRight;
_textField.keyboardAppearance = UIKeyboardAppearanceDark;
return _textField;
}
@end
And here is my table subclass.
@interface ManageWineViewController ()
@end
@implementation ManageWineViewController
- (id)init
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
self.title = @"Manage Wine";
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:self action:@selector(done)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(save)];
NSMutableArray *data = [[NSMutableArray alloc] init];
NSMutableDictionary *section = [[NSMutableDictionary alloc] init];
NSMutableArray *sectionData = [[NSMutableArray alloc] init];
[sectionData addObject:@{@"name": @"Estate", @"placeholder": @""}];
[sectionData addObject:@{@"name": @"Wine", @"placeholder": @""}];
[sectionData addObject:@{@"name": @"Vintage", @"placeholder": @"", @"keyboardType": [NSNumber numberWithInt:UIKeyboardTypeDecimalPad]}];
[section setObject:sectionData forKey:@"data"];
[data addObject:section];
section = [[NSMutableDictionary alloc] init];
sectionData = [[NSMutableArray alloc] init];
[sectionData addObject:@{@"name": @"Type"}];
[sectionData addObject:@{@"name": @"Style", @"placeholder": @"Select a Style", @"options": @[@"", @"Red", @"White", @"Rosé", @"Sparkling", @"Saké", @"Dessert, Sherry, and Port"]}];
[sectionData addObject:@{@"name": @"Appellation", @"placeholder": @""}];
[section setObject:sectionData forKey:@"data"];
[data addObject:section];
section = [[NSMutableDictionary alloc] init];
sectionData = [[NSMutableArray alloc] init];
[sectionData addObject:@{@"name": @"Alcohol %", @"placeholder": @"", @"keyboardType": [NSNumber numberWithInt:UIKeyboardTypeDecimalPad]}];
[section setObject:sectionData forKey:@"data"];
[data addObject:section];
self.data = data;
self.inputTexts = [[NSMutableDictionary alloc] initWithDictionary:@{@"0": @"",
@"1": @"",
@"2": @"",
@"10": @"",
@"11": @"",
@"12": @"",
@"20": @""}];
}
return self;
}
- (void)done
{
[self.currentTextField resignFirstResponder];
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)save
{
[self done];
}
- (void)hidePicker
{
[self.selectActionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.data.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return ((NSArray*)[[self.data objectAtIndex:section] objectForKey:@"data"]).count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *cellInfo = [((NSArray*)[[self.data objectAtIndex:indexPath.section] objectForKey:@"data"]) objectAtIndex:indexPath.row];
static NSString *CellIdentifier = @"EditorCell";
EditorFieldCell *cell = (EditorFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[EditorFieldCell alloc] init];
}
cell.textField.tag = [[NSString stringWithFormat:@"%i%i", indexPath.section, indexPath.row] integerValue];
cell.textField.delegate = self;
cell.name = cellInfo[@"name"];
cell.placeholder = cellInfo[@"placeholder"];
cell.text = [self.inputTexts objectForKey:[NSString stringWithFormat:@"%i", cell.textField.tag]];
if (cellInfo[@"keyboardType"])
{
cell.textField.keyboardType = [cellInfo[@"keyboardType"] integerValue];
}
else
{
cell.textField.keyboardType = UIKeyboardTypeDefault;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
#pragma mark - UITextFieldDelegate methods
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
self.currentTextField = textField;
if (textField.tag == 11)
{
//show select
NSArray *options = [[[[self.data objectAtIndex:1] objectForKey:@"data"] objectAtIndex:1] objectForKey:@"options"];
self.selectTextField = textField;
self.selectOptions = options;
[textField resignFirstResponder];
self.selectActionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
self.selectPickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
self.selectPickerView.showsSelectionIndicator = YES;
self.selectPickerView.dataSource = self;
self.selectPickerView.delegate = self;
[self.selectActionSheet addSubview:self.selectPickerView];
[self.selectActionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[self.selectActionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
[self.inputTexts setObject:textField.text forKey:[NSString stringWithFormat:@"%i", textField.tag]];
return YES;
}
@end
The error that I am getting with the crash is:
*** -[EditorFieldCell _didChangeToFirstResponder:]: message sent to deallocated instance 0x155f6e20
This is iOS 7 (and will only support iOS 7) if that helps.
Upvotes: 1
Views: 471
Reputation: 4671
You are not initialising EditorFieldCell
with reuse identifier.
EditorFieldCell *cell = (EditorFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
This condition will false.
if (!cell)
{
cell = [[EditorFieldCell alloc] init];
}
Try to create cell with reuseIdentifier
cell = [[EditorFieldCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
And write this in EditorFieldCell.m
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self == [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:self.textField];
}
}
Upvotes: 2