Im getting a crash, when using a UItextField, inside my customCell, and when i resignFirstResponder the textfield, but its not visible anymore(the table view scrolled out of window). I still can find the textfield, the pointer continues accessible, it is no null, and the crash only occurs on IOS7, on IOS6 i dont have this problem. Heres some code :
The textField is a global variable.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * CellIdentifier = [NSString stringWithFormat:#"Cell%d",indexPath.row];
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[TableCell alloc] init];
if(indexPath.row == 0)
{
[textField setFrame:CGRectMake(15, 5, cell.frame.size.width-60, cell.frame.size.height)];
textField.textAlignment = NSTextAlignmentLeft;
[textField setBorderStyle:UITextBorderStyleNone];
textField.textColor = [UIColor blackColor];
textField.tag = indexPath.row;
textField.delegate = self;
textField.secureTextEntry = YES;
[textField setFont:[UIFont fontWithName:#"Arial-BoldMT" size:15]];
textField.textColor = [UIColor whiteColor];
textField.returnKeyType = UIReturnKeyDone;
[textField setAdjustsFontSizeToFitWidth:YES];
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Senha" attributes:#{NSForegroundColorAttributeName: [UIColor whiteColor]}];
[cell.contentView textField];
}
}
return cell;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
// NSLog(#"text field %#",textField);
// NSLog(#"tfield return: %d",textField.isFirstResponder);
[textField resignFirstResponder];
// [self.view endEditing:YES];
return NO;
}
I've successfully fixed a similar crash bug with the help of Apple. The key is the reuseIdentifer.
The quote is from a mail from Vincent Gable of Apple Developer Technical Support:
This is a known behavior change that happens in iOS 7 with UITableView, when cells are not reused.
The fix here is to make sure that you follow proper cell reuse. If you do not want to re-use UITableViewCells, then it is recommended that you simply layout all your views inside a UIScrollView.
To make sure cells are re-used, make sure you are passing the same string to dequeueReusableCellWithIdentifier: that you pass to reuseIdentifier: when using alloc/init to make the cell. This string can not be nil.
So I think you should make sure you've set TableCell's reuseIdentifer property with the same value you've passed to dequeueReusableCellWithIdentifier:
You need to do some more research into how UITableViews work and reconsider your design. Storing a UITextField in a global variable and trying to position it like this is not the right approach. Even if you could solve the immediate problem, which is likely that the UITextField has been released along with the UITableViewCell, this design is only going to get you into trouble further down the line.
Instead, consider subclassing UITableViewCell and adding a UITextField property to your subclass.
You probably don't want to be using a different CellIdentifier for every single row either.
Maybe i've solved.
It's a little bit dirty methot but i think it work.
I store all the cell that cellForRowAtIndexPath create
if (!cell)
{
cell = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:#"FormCell_%#",cellID] owner:nil options:nil] lastObject];
[self.allTheCell addObject:cell];
}
the app doesn't crash anymore on ios7
Related
I just started Xcode objective-c recently and right now I'm trying to create a tableview with textfields in them to type. Ive looked into other stack overflow questions but many are from 6-8 years ago and seem to have a wide rage of answers and extremely complex. Could someone help me with the basics of how I can insert a textfield in a table view and give me some advice. Thanks!
Write this code in uitableview cell
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(110, 10, 185, 30)];
textField.clearsOnBeginEditing = NO;
textField.textAlignment = UITextAlignmentRight;
textField.delegate = self;
[aCell.contentView addSubview:txt];
You can do this as follows:
Drag and drop a UITableView in to your view
Drag and drop a UITableViewCell into your table.
Drag and drop a UITextField (or any
other UI component that you need)
I would suggest you to please refer tutorials for that like
1.https://videos.raywenderlich.com/courses/22-table-views-in-ios/lessons/8
2.https://www.appcoda.com/expandable-table-view/
They have best tutorials with all steps you can easily do whatever you want.
I hope it will help you.
Thanks.
Try below code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil) {
/*
* Actually create a new cell (with an identifier so that it can be dequeued).
*/
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
/*
* Now that we have a cell we can configure it to display the data corresponding to
* this row/section
*/
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(45, 30, 200, 40)];
tf.textColor = [UIColor colorWithRed:0/256.0 green:84/256.0 blue:129/256.0 alpha:1.0];
tf.font = [UIFont fontWithName:#"Helvetica-Bold" size:25];
tf.backgroundColor=[UIColor whiteColor];
tf.text=#"Hello World";
[cell.contentView addSubview:tf];
/* Now that the cell is configured we return it to the table view so that it can display it */
return cell;
}
You can create a custom cell. Add the textfield in it and use that in the table by registering the nib or class.
I have a simple tableView with 20 rows. I created a subclass custom UITableview cell, and in cellforRowAtIndex, I add a textfield to the cell once every other 3 rows. When I scroll up and down text fields show up in the wrong rows. Note, I can't make UItextfield part of my custom cell, because this can be anything, checkbox, radio button, but for simplicity I chose UITextfield... What am I doing wrong?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TestCellIdentifier";
testCell *cell = (testCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(!cell)
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
else{
//HMMM I also tried removing it before adding it- it doesn't work neither
for(UIView *v in cell.subviews){
if(v.tag == 999 ){
[v removeFromSuperview];
}
}
//add UItextField to row if it's divisible by 3
if(indexPath.row %3 ==0){
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(400, 10, 300, 30)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.font = [UIFont systemFontOfSize:15];
textField.placeholder = [NSString stringWithFormat:#"%d",indexPath.row];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.keyboardType = UIKeyboardTypeDefault;
textField.returnKeyType = UIReturnKeyDone;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.tag = 999;
[cell addSubview:textField];
}
}
cell.textLabel.text = [NSString stringWithFormat:#"%d",indexPath.row];
return cell;
}
don't use the Reusability ?
in this scene,i will not use the reusability
Reusing cells is a good thing and you should be able to do it.
You could consider removing the text field from the cell when it goes offscreen, before it is queued for reuse, in the delegate protocol method:
– tableView:didEndDisplayingCell:forRowAtIndexPath:
Knowing the row number you would know whether or not to remove the textfield.
Edited to add explanation:
On first glance your code looks OK, so I did a little test project.
The problem with your original code is that you're adding the textfield to the wrong "view" -- UITableViewCells have some structure that you need to pay attention to. Look at the documentation for the UITableViewCell contentView property. It says, in part:
If you want to customize cells by simply adding additional views, you
should add them to the content view so they will be positioned
appropriately as the cell transitions into and out of editing mode.
So the code should add to and enumerate subviews of the cell's contentView:
for(UIView *v in cell.contentView.subviews){
if(v.tag == 999 ){
[v removeFromSuperview];
}
}
...
textField.tag = 999;
[cell.contentView addSubview:textField];
I am having two labels created manually for displaying it in the tableviewcell named title and detail, code for displaying it are,
dealarray = [[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",nil];
detailarray = [[NSMutableArray alloc]initWithObjects:#"oneoneoneoneone oneoneoneoneoneoneoooooooo",#"two",#"three",#"fouronefouronefouronefouronefouronefouronefouron",nil];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
for(UILabel *lbl in [cell.contentView subviews])
{
[lbl removeFromSuperview];
}
cell.accessoryType= UITableViewCellAccessoryNone;
UILabel* title;
title= [[UILabel alloc] initWithFrame:CGRectMake(5,5,300,20)];
[cell.contentView addSubview:title];
[cell.contentView bringSubviewToFront:title];
[title setFont:[UIFont boldSystemFontOfSize:14]];
title.tag = 1001;
title.backgroundColor = [UIColor clearColor];
title.textColor = [UIColor blackColor];
title.text =[dealarray objectAtIndex:indexPath.row];
UILabel* detail;
detail= [[UILabel alloc] initWithFrame:CGRectMake(5,30,300,10)];
[cell.contentView addSubview:detail];
[cell.contentView bringSubviewToFront:detail];
[detail setFont:[UIFont systemFontOfSize:12]];
detail.tag = 1002;
detail.backgroundColor = [UIColor clearColor];
detail.textColor = [UIColor blackColor];
detail.text = [detailarray objectAtIndex:indexPath.row];
return cell
}
No problem in displaying those 2 labels and no problem in hiding all the 'detail' label and displaying the 'title' alone, the problem arises when I try to display the 'detail' label of the resp selective of cells.
Code tried:
// conti of cellforrowatindexpath
detail.numberOfLines = 3;
detail.lineBreakMode = NSLineBreakByWordWrapping;
if (a==-1)// declared 'a' in viewdidload as -1
{
((UILabel*)detail).hidden = YES;
}
else if(a==indexPath.row)
{
((UILabel*)detail).hidden = NO;
}
((UILabel*)detail).hidden = YES;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
a=indexPath.row;
[tableview reloadData];
}
Sorry for posting large amount of codes, it may help any one who is searching for the wholesome data of my doubt.
Whats the mistake am doing, I can't hide the detail label for resp selecting of cells. Can anybody help in this regard?
May I suggest you to use xcode functionnality to design your cell content? (as easy as drag and drop of UILabel on your cell for example) Then you will be able to access them from your code using their respective "tag" id.
A correct way of doing is detail here : http://www.appcoda.com/customize-table-view-cells-for-uitableview/
I think it's a better way than programmatically creating content for your cell, because using xcode interface you will be able to flawlessly define your interface.
Anyway to respond precisely to your question you should try to hide the detail label from "didSelectRowAtIndexPath" :
// Retrieve the corresponding cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// Get the detail label (using its tag) you set it to 1002
UILabel *detail = (UILabel *)[cell viewWithTag:1002];
// Hide it
detail.hidden = true;
Hope this help.
There is an error in your logic. You code as written will always set detail.hidden to YES, the 2 preceding if are ignored, thus this (BTW you don't need the type coercion and extra brackets):
if(a==-1) detail.hidden = YES;
else if (a==indexPath.row) detail.hidden = NO;
else detail.hidden = YES;
I have UITextField, i need to make it not to respond touches, because it is located on the UITableViewCell, and when user touches the textField, didSelectRowAtIndexPath is not getting called.
This textField has also clear button, i need to detect user taping on the clear button only, not in the rest textField area.
I tried, textField.userInteractionEnabled = NO. In this case clear button doesn't work of course, the same is with textField.enabled = NO;
UITextField *textField = [[UITextField alloc] initWithFrame:someFrame];
textField.textAlignment = NSTextAlignmentLeft;
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.delegate = self;
Help, please.
Thanks in advance.
In that case one work around can be used. You have to make a view that mask the textfield's text area but not clear button like this
We suppose that
someFrame = (20,50,100,44)
And textfield button around 20*20
So our view will be
UIView *maskView = [[UIView alloc] initWithFrame: CGRectMake (20,50,80,44)];
maskView.backgroundColor = [UIColor clearColor];
Add this view after your textfield added. And it will mask textfield's that area which used for text and leave button area as it is.
Remember, this is not tested and just a work around. So any other method is there than I recommend to you to use that. And change value according to your need.
Are you loading a cell from the nib or else. I have just tried to make my own custom cell like below
Assigning tag ( it is 9 in my sample ) for the uitextfield
In viewForCellAtIndex :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell ;
cell = [tableView dequeueReusableCellWithIdentifier:#"purchaseNibCell"];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"PurchaseNibCell" owner:self options:nil];
cell = self.purchaseCell;
self.purchaseCell = nil;
}
UITextField *text = (UITextField*)[cell viewWithTag:9];
text.enabled = NO; <------ if you have not done in the xib file.
cell.backgroundView = [[CustomCellBackground alloc] init];
UIImageView *accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"accessory.png"]];
cell.accessoryView = accessoryView;
return cell;
}
hope it helps
i´m adding a UITextField on a Cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
myLoc = [[UITextField alloc] initWithFrame:CGRectMake(35, 10, 250, 40)];
myLoc.adjustsFontSizeToFitWidth = YES;
myLoc.textColor = [UIColor blackColor];
myLoc.textAlignment = UITextAlignmentCenter;
myLoc.placeholder = #"Enter Location";
myLoc.returnKeyType = UIReturnKeyDone;
myLoc.autocorrectionType = UITextAutocapitalizationTypeNone;
myLoc.tag = indexPath.row;
myLoc.delegate = self;
[myLoc setEnabled:YES];
[cell addSubview:myLoc];
return cell;
}
and in the textFieldShouldReturn i would write the text from the textfield in a mutable array, and store in nsuserdefaults.
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[myLoc resignFirstResponder];
[locationArray addObject:textField.text];
locName = [NSUserDefaults standardUserDefaults];
[locName setObject:locationArray forKey:#"textName"];
[locName synchronize];
NSLog(#"Done pressed %#",myLoc.text);
return YES;
}
...but the myLoc.text is always null
any ideas for me?
In the delegate method, don't use myLoc to reference the textField, but use the actual textField pointer provided as parameter of the function. This one should actually point to the correct textfield and thus textField.text should have the correct value.
On a side note: Where do you define myLoc? It looks like you're trying to set a property on your viewcontroller. This way you'll always overwrite the property. For this you don't need a property at all, so just define myLoc locally in the function scope like UILabel *myLoc
You're better off creating your own custom UITableViewCell. You can see how to create one here:
tutorial
Trying to tack on to the existing UITableViewCell is difficult at best and impossible at worst. You're better off with custom cells.
Your text should never be NULL, since its an NSString. Are you sure you're talking about the text from the text field?
What outputs when you add NSLog(#%"#", textField.text); to your shouldReturn method?
Are you sure that you have typed in the text field? Also, even without typing, you should be getting #"" instead of nil.