Segmented UITable's unstability - iphone

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) {

Related

iOS - UITableView Changing Datasourse

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.

UITextField clears while scrolling in UITableView - custom cell

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.

How do you use custom UITableViewCell's effectively?

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

iPhone - 3 UITableViews with Custom cell

I'm having a view with 3 Table views.
Each table view will use one "Custom Cell View". I'm using the following code. But its showing only one table view. Can some one point me why? (All the arrays are filled with necessary objects)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* cellID = #"CustomSyncCell";
CustomCellView* cell = (CustomCellView*)[tableView dequeueReusableCellWithIdentifier:cellID];
if(cell == nil)
{
NSArray* nibObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCellView" owner:nil options:nil];
for(id currentObject in nibObjects)
{
if([currentObject isKindOfClass:[CustomCellView class]])
{
cell = (CustomCellView*)currentObject;
}
}
}
ObjectDetails* obj;
if(tableView == phoneNumbersTable)
{
obj = [phoneNumbersArray objectAtIndex:indexPath.row];
}
else if(tableView == mailIDsTable)
{
obj = [mailIDsArray objectAtIndex:indexPath.row];
}
else if(tableView == socialUpdatesTable)
{
obj = [socialUpdatesArray objectAtIndex:indexPath.row];
}
cell.keyLabel.text = [self returnPhoneType:obj.objKey];
cell.valueLabel.text = obj.objValue;
return cell;}
You have 2 options.
Set tag property on your tableViews and in the dataSource and Delegates methods test for that tag.
Make 3 objects and each objet set it for is specific tableView delegate and data source and put your code in that objects.
Hope that helps. If you will add all your data source and delegate methods more people will try to help.
The problem might be with the reuse identifier. Since you are using the cell with the same identifier for all the table views so, I think that is the cause of the problem. I also had this problem fixed it with the same manner. Create separate cells for each tableview with different identifier and reuse them.

"Warning reaching end of non-void function" with Multiple Sections that pull in multiple CustomCells within cellForRowAtIndexPath

I'm getting "Reaching end of non-void function" warning, but don't have anything else to return for the compiler. How do I get around the warning??
I'm using customCells to display a table with 3 Sections. Each CustomCell is different, linked with another viewcontroller's tableview within the App, and is getting its data from its individual model. Everything works great in the Simulator and Devices, but I would like to get rid of the warning that I have. It is the only one I have, and it is pending me from uploading to App Store!!
Within the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {, I have used 3 separate If() statements-(i.e.==0,==1,==2) to control which customCells are displayed within each section throughout the tableview's cells. Each of the customCells were created in IB, pull there data from different models, and are used with other ViewController tableViews.
At the end of the function, I don't have a "cell" or anything else to return, because I already specified which CustomCell to return within each of the If() statements.
Because each of the CustomCells are referenced through the AppDelegate, I can not set up an empty cell at the start of the function and just set the empty cell equal to the desired CustomCell within each of the If() statements, as you can for text, labels, etc...
My question is not a matter of fixing code within the If() statements, unless it is required. My Questions is in "How to remove the warning for reaching end of non-void function-(cellForRowAtIndexPath:) when I have already returned a value for every possible case: if(section == 0); if(section == 1); and if(section == 2).
*Code-Reference: The actual file names were knocked down for simplicity, (section 0 refers to M's, section 1 refers to D's, and section 2 refers to B's).
Here is a sample Layout of the code:
//CELL FOR ROW AT INDEX PATH:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Reference to the AppDelegate:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
//Section 0:
if(indexPath.section == 0) {
static NSString *CustomMCellIdentifier = #"CustomMCellIdentifier";
MCustomCell *mCell = (MCustomCell *)[tableView dequeueReusableCellWithIdentifier:CustomMCellIdentifier];
if (mCell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MCustomCell" owner:tableView options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[MCustomCell class]])
mCell = (MCustomCell *)oneObject;
}
//Grab the Data for this item:
M *mM = [appDelegate.mms objectAtIndex:indexPath.row];
//Set the Cell
[mCell setM:mM];
mCell.selectionStyle =UITableViewCellSelectionStyleNone;
mCell.root = tableView;
return mCell;
}
//Section 1:
if(indexPath.section == 1) {
static NSString *CustomDCellIdentifier = #"CustomDCellIdentifier";
DCustomCell *dCell = (DCustomCell *)[tableView dequeueReusableCellWithIdentifier:CustomDaddyCellIdentifier];
if (dCell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"DCustomCell" owner:tableView options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[DCustomCell class]])
dCell = (DCustomCell *)oneObject;
}
//Grab the Data for this item:
D *dD = [appDelegate.dds objectAtIndex:indexPath.row];
//Set the Cell
[dCell setD:dD];
//Turns the Cell's SelectionStyle Blue Highlighting off, but still permits the code to run!
dCell.selectionStyle =UITableViewCellSelectionStyleNone;
dCell.root = tableView;
return dCell;
}
//Section 2:
if(indexPath.section == 2) {
static NSString *CustomBCellIdentifier = #"CustomBCellIdentifier";
BCustomCell *bCell = (BCustomCell *)[tableView dequeueReusableCellWithIdentifier:CustomBCellIdentifier];
if (bCell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"BCustomCell" owner:tableView options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[BCustomCell class]])
bCell = (BCustomCell *)oneObject;
}
//Grab the Data for this item:
B *bB = [appDelegate.bbs objectAtIndex:indexPath.row];
//Set the Cell
[bCell setB:bB];
bCell.selectionStyle =UITableViewCellSelectionStyleNone;
bCell.root = tableView;
return bCell;
}
//** Getting Warning "Control reaches end of non-void function"
//Not sure what else to "return ???" all CustomCells were specified within the If() statements above for their corresponding IndexPath.Sections.
}
Any Suggestions ??
You need a return at the End of the function, regardless of whether you're handling the return inside of a {} block. Try:
return nil;
It'll never get executed, but you'll have a return for the compiler. I'd frankly redesign the statement.
Instead of using three separate if statements, change it to if() - else if() - else