[英]Why can't I initialize a UITextField from a subclass of UITableViewCell?
I've created a subclass of UITableViewCell
for an iPad app. 我为iPad应用程序创建了UITableViewCell
的子类。 I need to dynamically generate text fields, take input from the user, and then store that information in an array. 我需要动态生成文本字段,从用户那里获取输入,然后将该信息存储在数组中。 I thought of asking the UITableViewCell
for the UITextField.text
object, which would hold whatever the user wrote before my View Controller's segue (I'm saving the NSString
objects upon the segue being called). 我想到要向UITableViewCell
请求UITextField.text
对象,该对象将保存用户在View Controller进行Segue之前写的所有内容(在调用Segue时保存NSString
对象)。 So I've got an array of UITableViewCells which I ask for the UITextField
.text object. 因此,我有一个UITableViewCells数组,我需要UITextField
.text对象。 But for some reason while my UITableViewCell
subclass is being created, my UITextField
is not. 但是由于某种原因,在创建UITableViewCell
子类时,没有创建UITextField
。 I can call UITableViewSubclass
and it's initialized, but UITableViewSubclass.UITextField
is nil. 我可以调用UITableViewSubclass
并将其初始化,但是UITableViewSubclass.UITextField
为nil。
Here's my UITableViewCell
Subclass header (Yes, the UITextField
is connected in the storyboard): 这是我的UITableViewCell
子类标头(是的, UITextField
连接在情节提要中):
#import <UIKit/UIKit.h>
@interface ConditionCell : UITableViewCell
@property (strong, nonatomic) IBOutlet UITextField *condition;
@end
Here's my implementation file: 这是我的实现文件:
#import "ConditionCell.h"
@implementation ConditionCell
@synthesize condition;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.condition = (UITextField *)[self viewWithTag:10];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
This here is the Table View Controller handling the table that contains the cells: 这是Table View Controller,用于处理包含单元格的表:
.h file: .h文件:
#import <UIKit/UIKit.h>
#import "ConditionCell.h"
@interface ConditionsTableViewController : UITableViewController
@property (strong, nonatomic) NSMutableArray *conditionCellArray;
- (void)addNewConditionCell;
@end
.m file: .m文件:
#import "ConditionsTableViewController.h"
@interface ConditionsTableViewController ()
@end
@implementation ConditionsTableViewController
@synthesize conditionCellArray = _conditionCellArray;
- (NSMutableArray *)conditionCellArray
{
if (_conditionCellArray == nil) {
// Create the array object
_conditionCellArray = [[NSMutableArray alloc] init];
}
return _conditionCellArray;
}
- (void)addNewConditionCell
{
ConditionCell *condCell = [[ConditionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"conditionCell"];
[self.conditionCellArray addObject:condCell];
[self.tableView beginUpdates];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.conditionCellArray.count-1 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
[self.tableView reloadData];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.conditionCellArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"conditionCell";
ConditionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ConditionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
//cell.condition = (UITextField *)[cell viewWithTag:1];
return cell;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
@end
This Table View Controller lives inside a UIView Controller as the table view does not take up the whole screen. 该表视图控制器位于UIView控制器内部,因为表视图不会占据整个屏幕。 When the user presses an 'ok' button there is a segue that is triggered and it is here that I ask this Table View Controller for the array containing the UITableViewCells
, which I then run through a foreach to get their .text properties. 当用户按下“确定”按钮时,会触发一个选择,正是在这里我向此表视图控制器询问包含UITableViewCells
的数组,然后我通过一个foreach来获取其.text属性。 Unfortunately I can't seem to get anything I input into the text fields, hence the .text's are always nil. 不幸的是,我似乎无法在文本字段中输入任何内容,因此.text始终为零。 If anyone could help me with this issue it would be greatly appreciated! 如果有人可以帮助我解决这个问题,将不胜感激!
You might find this much easier to do using the free Sensible TableView framework. 使用免费的Sensible TableView框架,您可能会发现这样做更容易。 The framework has these text field cells out of the box, and can even create them automatically from your array. 该框架具有开箱即用的这些文本字段单元格,甚至可以从您的数组自动创建它们。
I figured out a better way to do what I wanted to do here that works. 我想出了一种更好的方法来做自己想做的事。 Turns out that the way iOS's UITableView works is totally different from what I wanted to do. 事实证明,iOS的UITableView的工作方式与我想要的完全不同。 UITableView works by looking at your storyboard and given the identifiers for the cells, it creates them and allows you to set their properties within the cellForRowAtIndexPath method. UITableView通过查看情节提要和给定的单元格标识符来工作,创建它们并允许您在cellForRowAtIndexPath方法内设置其属性。 However, when the cell goes offscreen, it is not retained as it's own separate object; 但是,当单元离开屏幕时,它不会保留,因为它是自己的单独对象。 it is reused. 它被重用。 So, you can think of it as if when you scroll a table view, the cells that disappear to one end reappear on the other end with new information. 因此,您可以认为它就像在滚动表格视图时,消失到一端的单元格在另一端再次出现新信息。 This is key - UITableView want YOU to provide the cell's information. 这是关键-UITableView希望您提供单元格的信息。 It was not made for input of information directly on a UITableViewCell, which is what I wanted to do. 我不是想直接在UITableViewCell上输入信息。
So what I ended up doing was copy-pasting my cells into their own .xib file, and in the subclass initWithStyle:reuseIdentifier method, do: 因此,我最终要做的是将单元格复制粘贴到自己的.xib文件中,并在子类initWithStyle:reuseIdentifier方法中执行以下操作:
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"ConditionCell" owner:self options:nil];
self = [nibArray objectAtIndex:0];
And that creates the cell with whatever style - setup - UI elements you want. 这样就可以创建具有任何样式的单元格-设置-所需的UI元素。
Next, I want to hold on to a reference to the cell, because that cell has a textbox, and I need to save what's on the textbox when the user presses a "done" button. 接下来,我要保留对该单元格的引用,因为该单元格具有一个文本框,并且当用户按下“完成”按钮时,我需要保存该文本框上的内容。 However, testing revealed the reuse problem I explained above. 但是,测试发现了我上面解释的重用问题。 So how to do this? 那么该怎么做呢? In my Table's view controller, whenever the user wants to add a new textbox (and presses the button to do so) I have a method which does 在我的表格的视图控制器中,每当用户想要添加一个新的文本框(并按下按钮来这样做)时,我都有一个方法
[self.conditionCellArray insertObject:[[ConditionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"conditionCell"] atIndex:0];
This adds a new cell to an array - this is important because I need to have a reference to ALL cells at all times. 这会向数组中添加新的单元格-这很重要,因为我需要始终引用所有单元格。 (It is adding the cell at index 0 because I want to insert it at the top). (它正在将单元格添加到索引0,因为我想将其插入顶部)。 Then, in the cellForRowAtIndexPath method, I did 然后,在cellForRowAtIndexPath方法中,我做了
return [self.conditionCellArray objectAtIndex:indexPath.row];
Which will return the corresponding cell. 它将返回相应的单元格。 Bear in mind, from what I have read this whole thing about keeping a reference to each and every cell in the table is contrary to Apple's stated best practices when using UITableView. 请记住,从我读到的所有有关保持对表中每个单元格的引用的内容来看,这与苹果公司使用UITableView时所说的最佳做法背道而驰。 However, as I said before, UITableView is meant to display information, not to gather it from user input. 但是,正如我之前说的,UITableView用于显示信息,而不是从用户输入中收集信息。 So this is why I had to break the rules, if you will, to achieve the desired effect (that I wanted). 因此,这就是为什么我必须违反规则才能达到预期的效果(我想要的)。 I hope this helps others who are looking to do the same thing; 我希望这对其他希望做同样事情的人有所帮助; and if there is a better way don't be shy about telling me. 如果有更好的方法,请不要羞于告诉我。
EDIT: Oh by the way, when you copy paste the cells created in storyboard to their own .xib file make sure to disconnect any IBOutlets and change their class back to UITableViewCell. 编辑:哦,顺便说一句,当您将在情节提要中创建的单元格复制粘贴到其自己的.xib文件中时,请确保断开所有IBOutlet的连接并将其类更改回UITableViewCell。 That way there won't be any problems or conflicts when you connect your .xib file cell. 这样,在连接.xib文件单元时就不会有任何问题或冲突。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.