I am trying to save certain values from UITextField however, I am unable to do that because whenever I scroll there is nothing in UITextField. I am using a custom cell. I understand that custom cell has to load in a specific view and for that reason I'm using textFieldDidEndEditing to store values in an array. However, I get the following error message:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Help is much appreciated!! My code is below and I'm quite new in IOS Development.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
if (indexPath.row == 7) {
static NSString *CellIdentifier = #"RevButtonCell";
RevButtonCell *cell = (RevButtonCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RevButtonCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
[cell.revsaveB addTarget:self action:#selector(revaddparse:) forControlEvents:UIControlEventTouchUpInside];
cell.reveditdeleteB.hidden = YES;
cell.reveditsaveB.hidden = YES;
cell.revsaveB.hidden = NO;
cell.revdeleteB.hidden = NO;
}
return cell;
} else {
static NSString *CellIdentifier = #"TextCell";
TextCell *cell = (TextCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TextCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
cell.detaillabel.text = [revdetailsA objectAtIndex:indexPath.row];
cell.detailtext.placeholder = #"Enter Text";
cell.detailtext.tag = indexPath.row;
cell.detailtext.delegate = self;
if (indexPath.row == 0) {
cell.detailtext.text = dateS;
}
if (indexPath.row == 1) {
cell.detailtext.text = clientS;
}
if (indexPath.row == 2) {
cell.detailtext.text = productS;
}
if (indexPath.row == 3) {
cell.detailtext.text = amountS;
}
if (indexPath.row == 4) {
cell.detailtext.text = qtyS;
}
if (indexPath.row == 5) {
cell.detailtext.text = taxS;
}
if (indexPath.row == 6) {
cell.detailtext.text = totalS;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[client insertObject:clientS atIndex:0];
[product insertObject:productS atIndex:0];
[date insertObject:dateS atIndex:0];
[amount insertObject:amountS atIndex:0];
[qty insertObject:qtyS atIndex:0];
[tax insertObject:taxS atIndex:0];
[total insertObject:totalS atIndex:0];
}
Initialize the vales of to empty string as
clientS = #"";
productS = #"";
dateS = #"";
amountS = #"";
qtyS = #"";
taxS = #"";
totalS = #"";
just use every CellIdentifier are different use CellIdentifier like bellow
and also here after use this code ,not required to create array and insert object in it so dont create array just use this code..
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d%d",indexPath.section,indexPath.row];
use this CellIndentifier insted of another like "TextCell" and "ButtonCell"
i hope this help you...
:)
It looks from your code like you are trying to implement static cells in a table view. What you might want to consider is using a storyboard and creating a table view that supports static table cells just using Interface Builder. This will allow you to eliminate the entire cellForRowAtIndexPath: method. If you can't use storyboards, then you will have to manage your cells the way you're doing it, but in my book, anytime you can eliminate code, you should.
If you're going to use a storyboard, there a couple things you should know:
Your view controller in the storyboard needs to be a table view controller
You set the table Content field to "Static Cells"
Add the textfields you want to use to each of the cells by dragging them into the cells you add
Create outlets in your view controller header and then drag connections to them in interface builder
There are some tutorials out there on using table views with static cells. They can be a little long, however, stick with them and you should be able to produce the results you're looking for.
Best regards.
Related
I was wondering if anyone knows how to solve this problem:
I have a UITableview, where the datasource can continue to grow. The issue is when I add elements to the data source, the table cells get messed up.
Each table cell has a text field where the user can enter data into it, but whenever I add data to the datasource the comments replicate to other cells.
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"ImageTableCell";
ImageTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
Picture *aPicture = (Picture *) [self.imageData objectAtIndex:[indexPath row]];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ImageTableCell" owner:self options:NULL];
cell = (ImageTableCell *)[nib objectAtIndex:0];
}
NSLog(#"comment %# index %d", aPicture.comment, [indexPath row]);
cell.cellImage.image = aPicture.picture;
cell.commentField.delegate = self;
cell.commentField.text = aPicture.comment;
cell.index = [indexPath row];
cell.tag = [indexPath row];
return cell;
}
self.imagedata is a NSMutabaleArray.
EDIT
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.imageData count];
}
-(void) reloadImages:(NSNotification *) aNotification {
self.imageData = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).currentUserData.images;
[self.imageTableView reloadData];
}
a screenshot http://www.mikerizzello.com/pic.png
Thanks
EDIT:
I think you might have a bad MVC pattern. Here's what I would do:
Take your custom cell, ImageViewCell, and make that class your textField delegate. Add a property for your custom Picture object, and set that in cellForRow...
Then, in your textFieldDelegate methods inside the custom cell class, you can change set the contents of your PictureObject there. I have a feeling that you're handling text input in the viewController, and the index of the data object in your array is getting mixed up and you're applying the comment field text to the wrong item in the array.
EDIT
I think it has something to do with cell reuse. The contents of your cell are not getting wiped out upon reusing a cell.
Try this block before you return the cell:
if (!aPicture.comment) {
cell.commentField.text = #"";
} else {
cell.commentField.text = aPicture.comment;
}
Have you try with
if (cell == nil) {
cell = (ImageTableCell*)[[ImageTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
Anyway you can also set different reuseIdentifier for each of cells but it will be bad idea, I would like to help you but i think need to run this project.
Please let me know if code above give better solution.
I am creating a table with three different types of custom cell, One of them, one custom cell is having UITextField. I create two rows using this custom cell. I set tag and delegate for textfields of both row.
My problem is, when I scroll the table, these rows with textfields move up and disappear from the screen, when scroll down, that time my app gets crash.
I get an error like
-[CellImageViewController txtField]: unrecognized selector sent to instance 0xa0ea5e0
Here is my code for cellForRowAtIndexPath:
if (indexPath.row == 0 )
{
if (cell == nil) {
cell = [[[CellWithTextFieldViewController alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID] autorelease];
}
cell.txtField.tag =1;
cell.txtField.delegate = self;
cell.txtField.text = #"kjfkd";
}
return cell;
}
else if(indexPath.row==1)
{
if (cell == nil) {
cell = [[[CellWithTextFieldViewController alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID] autorelease];
}
cell.txtField.tag = 2;
cell.txtField.text = #"glk";
cell.txtField.delegate = self;
return cell;
}
Any one have idea about this issue?
you have different type of cells, so you need to use a cellIdentifier different for each one.
Try this:
customOrNormalCell *cell [tableView dequeueReusableCellWithIdentifier:CellIdentifier]
if(!cell){
cell = [[CellWithTextFieldViewController alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:#"%i", indexPath.row]];
}
With this code, each cellIdentifier will be 1,2,3,4... (All different)
I'm pretty sure that it will solves the problem
create UITextField before create UITableView and Add your Textfield object in cell Content view
[cell.contentView addSubview:yourTxtFieldOblect];
It looks like you might be reusing a cell of a different type.
Try making sure which kind of class the cell you are reusing is before trying to access it's properties.
why you are define cell for each row?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d",indexPath.row];
CellWithTextFieldViewController *cell = (CellWithTextFieldViewController *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell =[[[CellWithTextFieldViewController alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]autorelease];
cell.txtField.tag = indexPath.row;
cell.txtField.text = [SET TEXT FROM ARRAY];
cell.txtField.delegate = self;
}
}
I had also faced this problem in my project.
just try this:
Disabled the scrolling property in Tableview and create a scrollview.Then add your Tableview in your scrollview.
UITableView *table=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 976, 395) style:UITableViewStylePlain];
[table setSeparatorStyle:UITableViewCellSelectionStyleNone];
UIScroll *scroll=[[UIScrollView alloc]initWithFrame:CGRectMake(24, 168, 978, 395)];
[table setScrollEnabled:NO];
[scroll addSubview:table];
[self.view addSubview:scroll];
[scroll sendSubviewToBack:table];
Try this
static NSString *cellIdentifier= #"Cell";
CellWithTextFieldViewController *cell = (CellWithTextFieldViewController *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[CellWithTextFieldViewController alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.txtField.tag =indexPath.row+1;
cell.txtField.delegate = self;
cell.txtField.text = #"kjfkd";
return cell;
While scrolling tableView your cell is getting reused. Thats why textField is disappearing. Try to use different cell id for different custom cells. Dont forget to give the same id in nib file for cell identifier
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *customCellOne = #"customCell1";
static NSString *customCellTwo = #"customCell2";
UITableViewCell *cell =nil;
if (0 == indexPath.row)
{
cell = (CustomCellOne *)[tableView dequeueReusableCellWithIdentifier:customCellOne];
if (nil == cell)
{
// Create custom cell one and do what ever you want
}
}
else if (1 == indexPath.row)
{
cell=(CustomCellTwo *)[tableView dequeueReusableCellWithIdentifier:customCellTwo];
if (nil == cell)
{
// Create custom cell two and do what ever you want
}
}
return cell;
}
I don't know,may be when reused the cell,the textfield delegate was released.
may be you can set the
textfield.deleagate = self;
in CellWithTextFieldViewController.m
Create a Table View.
then create a customize table View cell and place a button on cell and Now I try to get Table View index when click on index.
But when I click on button that place on cell It's not giving me the Index of list.
My Table View class name is SubMenuViewController and cell class name is SubMenuCell
and my code of SubMenuViewController is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ModelLocator *model = [ModelLocator getInstance];
static NSString *simpleTableIdentifier = #"SubMenuCell";
SubMenuCell *cell = (SubMenuCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SubMenuCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (model.foodSubItemList) {
FoodSubItemVO* foodSubItemTemp = [model.foodSubItemList objectAtIndex:indexPath.row];
[cell.lbSubFoodItem setText: foodSubItemTemp.foodSubItemName];
[cell.lbPrice setText: foodSubItemTemp.price];
[cell setIndexPath:indexPath];
}
return cell;
}
and My SubMenuCell code here
- (IBAction)addItemIntoOrder:(id)sender {
NSLog(#"#%",indexPath);
NSLog(#"#%",indexPath.row);
}
indexPath declare in SubMenuCell.h
Your NSLog's are faulty; try this instead (mind that changed % and # order).
- (IBAction)addItemIntoOrder:(id)sender
{
NSLog(#"%#",indexPath);
NSLog(#"%#",indexPath.row);
}
Make sure that the addItemIntoOrder: action is hooked up to your delegate correctly in IB.
I have a table that has its content filled using one of the two datasets provided based on the value of the segmented control attached. The data is pulled from the web.
The application crashes when I move back and forth between the two datasets and then select a table cell. The application works without hiccups when I use two separate table rather than a single table with a segmented control. Somehow combining them renders the application unstable.
One of the most error is when I tapped one the Acells of A table and while its loading I tapped the segment index=1, which will load B. it cause unrecognized selector being sent. meaning of the parameter o A table to being sent to B table.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier0;
if (choice == 0) {
CellIdentifier0 = #"ACell";
} else if (choice == 1) {
CellIdentifier0 = #"BCell";
}
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier0];
if (cell == nil) {
if (choice == 0) {
[[NSBundle mainBundle] loadNibNamed:#"ACell" owner:self options:nil];
cell = ACell;
self.ACell = nil;
} else if (choice == 1) {
[[NSBundle mainBundle] loadNibNamed:#"BCell" owner:self options:nil];
cell = BCell;
self.BCell = nil;
}
}
if (choice == 0) {
[(ACell *)cell setA:(A*)[contentArray objectAtIndex:indexPath.row]];
} else if (choice == 1) {
[(BCell *)cell setB:(B*)[contentArray objectAtIndex:indexPath.row]];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( choice == 0) {
A = [contentArray objectAtIndex:indexPath.row];
[[NSNotificationCenter defaultCenter] postNotificationName:#"showA" object:A];
} else if (choice ==1) {
B = [contentArray objectAtIndex:indexPath.row];
[[NSNotificationCenter defaultCenter] postNotificationName:#"showB" object:B];
}
}
Assuming that ACell has the retained value when the nib file is loaded, doing self.ACell = nil; will release the older value and set ACell to nil. Now the older value is the one pointed to by cell. So technically it would be pointing to junk as it would've been deallocated because ACell is the only variable retaining the object. You can fix this by replacing,
cell = ACell;
with,
cell = [[ACell retain] autorelease];
As a sidenote, in the didSelectRowAtIndexPath: method you're doing } else if (choice = 1) {. Make sure you use == rather than = which will always evaluate to true along with changing the value of choice although it is unlikely in this case.
check choice spellings
if (choicee==0) {
[[NSBundle mainBundle] loadNibNamed:#"ACell" owner:self options:nil];
cell = ACell;
self.ACell = nil;}
else if (choice==1) {
I am currently making a custom UITableView cell as shown below.
The custom UITableViewCell is in its own nib file that I am calling from another ViewController. (like so)
// RegistrationViewController.m
//Sets number of sections in the table
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
// Sets the number of rows in each section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
//Loads both Custom cells into each section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Registration Cell
static NSString *CellIdentifier = #"CustomRegCell";
static NSString *CellNib = #"LogInCustomCell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
}
//Registration Button
static NSString *CellButtonIdentifier = #"CustomSubmitCell";
static NSString *CellButtonNib = #"LogInSubmitButton";
UITableViewCell *cellButton = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellButtonIdentifier];
if (cellButton == nil) {
NSArray *nibButton = [[NSBundle mainBundle] loadNibNamed:CellButtonNib owner:self options:nil];
cellButton = (UITableViewCell *)[nibButton objectAtIndex:0];
}
if (indexPath.section == 0) {
cell.selectionStyle = UITableViewCellSelectionStyleNone; //Stops the UITableViewCell from being selectable
[self registrationControll];
//TODO: call method that controls this cell
return cell;
}
if (indexPath.section == 1) {
cellButton.selectionStyle = UITableViewCellSelectionStyleNone; //Stops the UITableViewCell from being selectable
return cellButton;
}
return nil;
}
It has four text fields that I am wanting to limit the size of the string that can be entered to five. (I'm only trying it with the first text field so far but its not even entering the textField:shouldChangeCharactersInRange:replacementString: delegate method (found this out while debugging the app) here is the code for the part I am trying to restrict the amount of characters that can be entered.
// RegistrationViewController.m
//textField:shouldChangeCharactersInRange:replacementString:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
int length = [regFieldOne.text length] ;
if (length >= MAXLENGTH && ![string isEqualToString:#""]) {
regFieldOne.text = [regFieldOne.text substringToIndex:MAXLENGTH];
return NO;
}
return YES;
}
I think I have limited my error to one of two things.
Maybe I haven't set everything up in interface builder correctly.
OR it has something to so with delegation... which I have a general understanding of and is why I think the issue might be here, but with such a complex file structure I'm not sure how or if this is right.
Any help, explanations, suggestions etc would be greatly appreciated.
At some point, you need to set the delegate for the textField
Since you put the delegate method in RegistrationViewController.m, you can set the delegate right after adding the cell in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.
As long as you are returning a subclass of UITableViewCell from LogInCustomCell.xib, you can use something like this:
LogInCustomCell *cell = (LogInCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (LogInCustomCell *)[nib objectAtIndex:0];
}
cell.textField1.delegate = self;
cell.textField2.delegate = self;
cell.textField3.delegate = self;
cell.textField4.delegate = self;
...
return cell;
From what I can see
You have the delegate methods in RegistrationViewController.m
But you are idnicating that CustomRegCell is the delegate, so the delegate methods should be there