Adding items to table view in popover - objective-c

In my application I have the array, which create in Main_View_Controller from json response in loop:
Main_View_Controller.m
NSMutableArray *Cities = [[NSMutableArray alloc] init];
while (ItemsFromParsedResponse = (NSDictionary *)[enumerator nextObject]) {
AppDelegate *dataCenter = (AppDelegate*)[[UIApplication sharedApplication] delegate];
dataCenter.CityLabel = [ItemsFromParsedResponse objectForKey:#"label"];
[Cities addObject:dataCenter.CityLabel];
dataCenter = nil;
}
AppDelegate *dataCenter = (AppDelegate*)[[UIApplication sharedApplication] delegate];
dataCenter.CityInfo = Cities;
This array must be presented in Popover, containing TableView. I've trying to delegate array to popover same like delegate it to AppDelegate, but it's not work. If I read dataCenter.CityInfo in my CityList_Popover_Contoller, it has nil value.
CityList_Popover_Controller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{//some standard code
AppDelegate *dataCenter = (AppDelegate*)[[UIApplication sharedApplication] delegate];
cell.textLabel.text = [dataCenter.CityInfo objectAtIndex:indexPath.row];
[tableView reloadData];
return cell;
}
How can I load CityInfo only if it is not-nil? And how can I tracking changes in this array and dynamically update table content according new data in array?
Sorry if my question too simple, but I spent a lot of time to make it work.
Thanks for any advice!

Just a simple if-check should work:
AppDelegate *dataCenter = appDelegate;
if ([dataCenter.CityInfo objectAtIndex:indexPath.row])
{
cell.textLabel.text = [dataCenter.CityInfo objectAtIndex:indexPath.row];
}
else
{
NSLog(#"Whoops, null data at row %i", indexPath.row);
}
// NEVER call reload data here, you are
// already reloading data when this
// method is called, will end up in corruption.
// [tableView reloadData];
return cell;

Related

UITableView reloads incorrectly after removeObjectAtIndex and reloadData

I have a UITableView which has data from an NSMutableArray.
When calling removeObjectAtIndex on the array and then reloadData on the table, the cell is removed fine, but then scrolling shows the table hasn't reloaded properly.
The code I am using is:
[_squadArray removeObjectAtIndex:myIndex;
[[self tableView] reloadData];
This is what the table looks like afterwards:
FYI, the table should be full and not stop where it stops.
Update: cellForRowAtIndexPath method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier;
MyIdentifier = #"cell";
ClubSquadPlayerTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
PFObject *object = [_squadArray objectAtIndex:indexPath.row];
cell.playerNameLabel.text = [NSString stringWithFormat:#"%# %#", [object valueForKey:#"first_name"], [object valueForKey:#"last_name"]];
cell.squadNumberLabel.text = [[object valueForKey:#"squad_number"] stringValue];
cell.positionLabel.text = [object valueForKey:#"position"];
if ([[object valueForKey:#"fitness_status"] isEqualToString:#"Fit"])
{
cell.fitnessStatusImageView.image = [UIImage imageNamed:#"fit"];
} else if ([[object valueForKey:#"fitness_status"] isEqualToString:#"Doubtful"])
{
cell.fitnessStatusImageView.image = [UIImage imageNamed:#"doubtful"];
} else if ([[object valueForKey:#"fitness_status"] isEqualToString:#"Injured"])
{
cell.fitnessStatusImageView.image = [UIImage imageNamed:#"injured"];
}
return cell;
}
It seems to me like your problems can be solved by Parse's own UI.
The Parse UI version of a UITableViewController is a PFQueryTableViewController. You can still use your custom cells and outlets, but the controller is a bit different.
In this case your issue will be solved by the [yourTable loadObjects] function which allows you to update your table from the PFQuery.
You set up the PFQueryTableViewController directly from a PFQuery without arrays. See more here.
When you try to remove the object as i saw it have santax error
Your code is
[_squadArray removeObjectAtIndex:myIndex;
[[self tableView] reloadData];
But it should be
[_squadArray removeObjectAtIndex:myIndex];
[[self tableView] reloadData];
There were ] missing

UITableView is null after first data load, reloadData does not work

I have a custom UIView with a UITableView in it. I connect the delegate and dataSource via interface builder, it looks like this: http://postimg.org/image/nj9elaj4h/ (may not upload images yet :( )
When I load the view, the data is displayed as it should be. But when I try to call reloadData, nothing happens. I checked if the uitableview is set, but it is NULL. But as soon as I drag the tableView and it reloads it views, the new data is presented. Anyone got an idea why reloadData does not work?
.h looks like this:
#interface NextTitleView : UIView<UITableViewDataSource,UITableViewDelegate,SociusClientDelegate,UIActionSheetDelegate,Ne xtTitleCustomCellDelegate>
{
NexTitleCustomCell* _cellInFocus;
}
#property(nonatomic,retain)IBOutlet UITableView* _tableViewNextTitle;
#end
thanks for your help :D
EDIT: Added .m file
#implementation NextTitleView
#synthesize _tableViewNextTitle;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(id)init
{
if(self)
{
[SharedSingeltons sharedInstance]._client.delegateCustomClient = self;
_tableViewNextTitle = [[UITableView alloc]init];
}
return self;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if(section == 0)
return #"Now playing";
if(section == 1)
return #"Comming Next";
else
return #"";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section == 0)
return 1;
if (section == 1)
return [[SharedSingeltons sharedInstance]._client._musicList count];
else
return 0;
}
-(NexTitleCustomCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NexTitleCustomCell* cell = [[NexTitleCustomCell alloc]init];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"NextTitleCustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
MusicItem* item = [[SharedSingeltons sharedInstance]._client._musicList
objectAtIndex:indexPath.row];
cell.delegate = self;
cell._labelSongTitle.text = item._songTitle;
cell._labelSongTitle.textColor = [UIColor blackColor];
cell._labelSubtitle.text = item._artist;
cell._identifier = item._songIdentifier;
cell._labelRating.text = item._rating.stringValue;
return cell;
}
-(void)clientDidReceiveMusicList:(SociusClient *)sender list:(NSMutableArray *)array
{
for(MusicItem* item in [SharedSingeltons sharedInstance]._client._musicList)
{
NSLog(#"rating:%#",item._rating);
}
NSLog(#"TAbleVIEW:%#",_tableViewNextTitle);
[self._tableViewNextTitle reloadData];
}
-(void)didPressActionButton:(NexTitleCustomCell *)sender
{
NSLog(#"Show alert view");
_cellInFocus = sender;
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Vote Up", #"Like",#"Remember", nil];
[popupQuery showInView:self];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)
{
NSLog(#"Vote up");
[self sendUpdateVoteForSong];
}
}
-(void)sendUpdateVoteForSong
{
NSMutableDictionary* dict = [[NSMutableDictionary alloc]init];
[dict setObject:_cellInFocus._identifier forKey:#"Vote"];
NSLog(#"Identifier:%#",_cellInFocus._identifier);
[[SharedSingeltons sharedInstance]._client sendObject:dict error:nil];
}
#end
I would say you are calling reload data too soon, probably in initWithNibName, you should be calling it in viewDidLoad.
I just set up a uiviewcontroller to handle the view. Now it works fine.
I think that UIActionSheet led to the problem,you can try to reloadData twice.
I noticed you are New-ing your Table view, but it's an Outlet... You don't need to alloc init your table view, if it's an IBOutlet. So either get rid of the IBOutlet, and just declare it as a property (but then you need to make sure you lay out your Table view programmatically), or keep the IBOutlet, and get rid of the code to alloc init it. Currently also your datasource and delegate are set from IB, so if you alloc init your table view, those won't be set anymore...
The tableview outlet should NOT be nil.
Can you put a breakpoint in awakeFromNib, and see if the TableView outlet is NIL there?
Are you loading the View Class that contains the table view by using its NIB file properly?
If you just embed the View class in the storyboard, it will not load the NIB automatically. I usually use a View container in that case, then load the NIB programmatically, and embed the loaded view in the view container programmatically.
NSArray *arrayXibObjects = [[NSBundle bundleWithIdentifier:#"net.mycompany.myappid"] loadNibNamed:#"myNibName" owner:nil options:nil];
for (id object in arrayXibObjects) {
if ([object isKindOfClass:myNibsClass]) {
return object; // this is your class loaded from NIB
}
}
This code can be placed in a utility method, to make it accessible with 1 line of code.
The returned Class is going to have the IBOutlets connected from the NIB to it's respective Class.
Now check in the debugger:
po [loadedClassFromNib tableView] // should not be NIL
Then embed the loaded NIB in the container like this: (or use constraints)
[self.viewContainer addSubview: classLoadedFromNib];
classLoadedFromNib.frame = self.viewContainer.frame;

Why is my app crashing during Table View Insert Row?

My app is only crashing in a specific way. Here's a break down of what's going on.
I can type in text in a UITextView and tap a button that saves the text and adds a row to a UITableView in another UIViewController. I can then tap on the desired cell from the UITableView and that UIViewController will dismiss and the text will appear again on the main UIViewController.
I have another button that simply clears out the UITextView so I can type in new text.
If I view the text from an added row and then tap the "Add" button to input new text and then tap the "Save" button my app crashes.
Here's some of the code:
didSelectRow Code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Setting the text stored in an array into a NSString here
_displayString = [_savedNoteArray objectAtIndex:indexPath.row];
[self dismissViewControllerAnimated:YES completion:nil];
}
save button code:
- (IBAction)saveNote
{
if (_noteView.aTextView.text == nil)
{
[_noteArray addObject:#""];
Note * tempNote = [[Note alloc] init];
_note = tempNote;
[_savedNotesViewController.savedNoteArray addObject:tempNote];
NSIndexPath * tempNotePath = [NSIndexPath indexPathForRow: [_savedNotesViewController.savedNoteArray count]-1 inSection:0];
NSArray * tempNotePaths = [NSArray arrayWithObject:tempNotePath];
[_savedNotesViewController.noteTableView insertRowsAtIndexPaths:tempNotePaths withRowAnimation:NO];
[[NSNotificationCenter defaultCenter] postNotificationName:#"AddNote" object:nil];
}
else
{
[_noteArray addObject:self.noteView.aTextView.text];
Note * tempNote = [[Note alloc] init];
_note = tempNote;
[_savedNotesViewController.savedNoteArray addObject:tempNote];
NSIndexPath * tempNotePath = [NSIndexPath indexPathForRow:[_savedNotesViewController.savedNoteArray count]-1 inSection:0];
NSArray * tempNotePaths = [NSArray arrayWithObject:tempNotePath];
//**** This is where the app is crashing *****
[_savedNotesViewController.noteTableView insertRowsAtIndexPaths:tempNotePaths withRowAnimation:NO];
[[NSNotificationCenter defaultCenter] postNotificationName:#"AddNote" object:nil];
}
Note * myNote = [Note sharedNote];
myNote.noteOutputArray = _noteArray;
}
add butt code (makes a new UITextView):
- (IBAction)addButtonTapped
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"AddNote" object:nil];
}
in my viewWillAppear to show the selected row text I do this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.noteView.aTextView.text = _savedNotesViewController.displayString;
}
note code (singleton class):
static Note * sharedNote = nil;
- (id)initWithNote:(NSString *)newNote
{
self = [super init];
if (nil != self)
{
self.note = newNote;
}
return self;
}
+ (Note *) sharedNote
{
#synchronized(self)
{
if (sharedNote == nil)
{
sharedNote = [[self alloc] init];
}
}
return sharedNote;
}
When the app crashes I get this:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Note isEqualToString:]: unrecognized selector sent to instance 0x8875f20'
Stepping through my code, the text is being added to the array, but when it comes time to insertRowsAtIndexPaths the app blows up.
Any advice is much appreciated!
* EDIT // TableView Code **
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_savedNoteArray count];
}
- (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];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
//I have a feeling this could be where an issue is.
NSString * cellString = [_savedNoteArray objectAtIndex:indexPath.row];
cell.textLabel.text = cellString;
return cell;
}
One potential issue (which may not be your crash, but will cause issues regardless) is that you are storing Note objects in the savedNoteArray BUT you are trying to use them as strings (your code below):
//Setting the text stored in an array into a NSString here
_displayString = [_savedNoteArray objectAtIndex:indexPath.row];
Then you assign that displayString to a UITextView's text property (which is supposed to be an NSString*):
self.noteView.aTextView.text = _savedNotesViewController.displayString;
The short form of this issue can be summarized as...
Note *note = [[NSNote alloc] init];
[array addObject:note];
textView.text = array[0];
This will clearly cause issues. You're basically assigning a 'Note' object to something that is supposed to be a string.
This probably leads into the crash that you're experiencing in the cellForRowAtIndexPath: method of your table view data source. Are you using Note objects there as well, or are you properly assigning NSStrings to views?

Reload TableView data after click button

I'm making chat application and read messages data from SQLite database. I want to reload my TableView data with new messages after clicking on my "send" button.
Event for my button:
[_sendButton addTarget:self action:#selector(saveMessage:) forControlEvents:UIControlEventTouchUpInside];
I think I need to use -(void)viewDidAppear:(BOOL)animated but it didn't work (or I'm doing something wrong).
[_tableView reloadData];
-(void)viewDidAppear:(BOOL)animated {
sqlite3 *database;
databaseName = #"Messenges.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
messenges = [[NSMutableArray alloc] init];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select * from messenges";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *dbMessageText = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
Message *messege = [[Message alloc] initWithName:dbMessageText];
[messenges addObject:messege];
[messege release];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);}
Editing
This is my method to add a new row to TableView. New row must be added at once after clicking "send" button.
-(IBAction)insertRows:(id)sender {
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
[messenges insertObject:[[NSString alloc] initWithFormat:#"%#", _textField.text] atIndex:appDelegate.messenges.count+1];
NSArray *insertIndexPaths = [NSArray arrayWithObject: [NSIndexPath indexPathForRow:1 inSection:1]];
UITableView *tV = (UITableView *)self.tableView;
[tV beginUpdates];
[tV insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
[tV endUpdates];}
But this code give me error: 'Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source.'
How can I fix it?
Edit2
Ok. I have only 1 section. numberOfSectionsInTableView: does not require correction.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
NSUInteger numberOfRowsInSection = appDelegate.messenges.count; //add new variable to what rows will be +1
if (self.editing) {
numberOfRowsInSection++;
}
return numberOfRowsInSection;}
But I still have the same error.
Edit #3
Let's look. I changed my insertRows to :
-(IBAction)insertRows:(id)sender {
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
[self.tableView beginUpdates];
self.tableView.editing = YES;
[messenges insertObject:[[NSString alloc] initWithFormat:#"%#", _textField.text] atIndex:appDelegate.messenges.count+1];
NSArray *insertIndexPaths = [NSArray arrayWithObject: [NSIndexPath indexPathForRow:appDelegate.messenges.count+1 inSection:1]];
[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
}
And numberOfRowsInSection:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
NSUInteger numberOfRowsInSection = appDelegate.messenges.count;
if (self.tableView.editing) {
numberOfRowsInSection++;
}
NSLog(#"%i",numberOfRowsInSection);
return numberOfRowsInSection;
}
But I got an error *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 3]' . Then I corrected if (self.tableView.editing) to:
if (self.tableView.editing) {
MDAppDelegate *someNewDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
numberOfRowsInSection = someNewDelegate.messenges.count+1; //or .count
}
But got same error about 'NSRangeException'.
To update your UITableView with animation you need to:
Invoke beginUpdates on your UITableView
Update your data model
Insert / Remove rows and sections
Invoke endUpdates on your UITableView
Couple of Things to Keep in Mind:
If you are deleting a section you should not also be deleting rows from that section (unnecessary and might even cause errors)
If you are inserting a section you should not also be inserting rows into that section (UITableView will call numberOfRowsInSection: followed by cellForRowAtIndexPath: if the cell is visible).
What Do You Mean, Update My Data Model?
If you are manipulating a UITableView by adding and removing rows and sections, then you should have some way of keeping track of what sections / rows are currently in the UITableView at any given moment.
For example, you should have a numberOfRowsInSection: method that resembles this:
- (NSInteger)numberOfRowsInSection:(NSInteger)section
{
// You should have a way to get section data with an index (section)
// The below example assumes an NSArray named self.mySectionCollection
// exists for this purpose
NSArray *sectionList = self.mySectionCollection;
// You should have data associated with a section. Below its assumed
// this data is wrapped in an NSDictionary. Data that might be in here
// could include a height, a name, number of rows, etc...
NSDictionary *sectionData = [sectionList objectAtIndex:section];
NSInteger rowCount = 0;
// SectionData should NEVER be nil at this point. You could raise an
// exception here, have a debug assert, or just return 0.
if (sectionData)
{
rowCount = [[sectionData objectForKey:#"rowCount"] intValue];
}
return rowCount;
}
You can store information about sections / rows in several different ways including using CoreData. The point is that by modifying this collection in between beginUpdates and endUpdates you are telling the UITableView how to update itself (it will query numberOfRowsInSection:, numberOfSections, and cellForRowAtIndexPath: as needed).
Edit
I believe if you modify your insertRows: method to modify your data source (messenges) at the same time you notify UITableView that updates have occurred that things will begin working for you properly.
Try using this code:
-(IBAction)insertRows:(id)sender
{
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
UITableView *tV = (UITableView *)self.tableView;
[tV beginUpdates];
// UPDATE DATA MODEL IN BETWEEN beginUpdates and endUpdates
int rowIndex = appDelegate.messenges.count + 1;
[messenges insertObject:[[NSString alloc] initWithFormat:#"%#", _textField.text]
atIndex:rowIndex];
// Notify UITableView that updates have occurred
NSArray *insertIndexPaths = [NSArray arrayWithObject:
[NSIndexPath indexPathForRow:rowIndex inSection:1]];
[tV insertRowsAtIndexPaths:insertIndexPaths
withRowAnimation:UITableViewRowAnimationRight];
[tV endUpdates];
}
Edit #2
If you are still having issues, I would look at where you are setting the self.editing flag.
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
//add new variable to what rows will be +1
NSUInteger numberOfRowsInSection = appDelegate.messenges.count;
if (self.editing)
{
numberOfRowsInSection++;
}
return numberOfRowsInSection;
}
This flag controls whether an additional row exists in the table or not. For this reason, you must set it between beginUpdates and endUpdates like:
// assuming the editing flag is set from some IBAction
-addNewRow:(id)sender
{
int row = ???; // not sure where you want this new row
[self.tableView beginUpdates]
self.editing = YES;
NSArray *insertIndexPaths = [NSArray arrayWithObject:
[NSIndexPath indexPathForRow:row inSection:1]];
[self.tableView insertRowsAtIndexPaths:insertIndexPaths
withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
}
Remember to similarly call deleteRowsAtIndexPaths:withRowAnimation: if the user stops editing if you are removing the row you add. I believe no action is necessary if the edit becomes permanent, but you'd need to set self.editing = NO while also adding a new row to it's proper place in self.messenges.
Also, in your insertRows: method, you telling the UITableView that you are inserting a row at index 1 when in fact you always insert at the end of the messenges collection. I've modified my version of the insertRows method so that it has a rowIndex variable for the purpose of ensuring the same index is used when updating the data model and informing UITableView of the change.
Lastly, please include as much debugging information as possible when you run into problems. Usually when a problem arises from updating the UITableView in the manner you are trying, it will tell you there is an inconsistency error. It's been awhile since I've seen it, but something to the effect that before updating the table there were 5 number of rows and after there were 7 when only 1 was added. I'd like to see this message if it is showing up in your console.
Edit #3
This is in response to the error you are seeing:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 ..
3]'
Your error has nothing to do with inserting into the UITableView. It has to do with the fact that you are trying to insert beyond the bounds of an array. My guess is the offending line is:
[messenges insertObject:[[NSString alloc] initWithFormat:#"%#",
_textField.text]
atIndex:appDelegate.messenges.count+1];
To insert at the end of the array, use an index of appDelegate.messenges.count (removed the +1).
Also... Are you absolutely certain your data model and calls to update the UITableView agree? Try invoking NSLog(#"rowsBeforeUpdate: %i", [self numberOfRowsInSection:0]); just after you call beginUpdates and just before calling endUpdates. Also, call NSLog(#"inserting index paths: %#", insertIndexPaths) when informing the UITableView of an insert operation. My guess is that self.messenges accurately reflects the rows that should be in the table, but by adding +1 when self.tableView.editing is true, you push the numberOfRowsInSection: above what you report in your calls to insertRowsAtIndexPaths:withRowAnimation:.
Try this:
-(IBAction)insertRows:(id)sender {
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
[self.tableView beginUpdates];
NSLog(#"rows before update: %i", [self numberOfRowsInSection:0]);
self.tableView.editing = YES;
NSLog(#"rows with editing flag set: %i", [self numberOfRowsInSection:0]);
int rowIndex = appDelegate.messenges.count; // don't need +1 at end
int sectionIndex = 0; // should it be 0 or 1? I would guess 0
[messenges insertObject:[[NSString alloc] initWithFormat:#"%#", _textField.text]
atIndex:rowIndex];
NSArray *insertIndexPaths = [NSArray arrayWithObject:
[NSIndexPath indexPathForRow:rowIndex
inSection:sectionIndex]];
[self.tableView insertRowsAtIndexPaths:insertIndexPaths
withRowAnimation:UITableViewRowAnimationRight];
NSLog(#"inserting index paths: %#", insertIndexPaths);
[self.tableView endUpdates];
}
I changed the row index above to exclude the +1 in it. I changed the section index to be 0, which should be correct unless this UITableView does in fact have multiple sections that haven't been mentioned. Make sure that your logs make sense. If you see numberOfRowsInSection: increase by two during the course of insertRows: then you had also better see insertRowsAtIndexPaths: reflect the same thing. I'm confused why you need the editing flag to add another row in your numberOfRowsInSection: method. This part (where you add an additional row if self.editing is set) doesn't seem to be working right. Perhaps just try leaving out this part to have some of it working, then add it back in once you have some things working properly. Perhaps change numberOfRowsInSection: to be like the following until some things begin working:
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
NSUInteger numberOfRowsInSection = appDelegate.messenges.count;
NSLog(#"numberOfRowsInSection %i: %u", section, numberOfRowsInSection);
return numberOfRowsInSection;
}

Initialize NSMutableArray

Im very new in xcode 3 and i really need help for this
I developed my apps using UITableView and XML to showed the content.
i had 3 .xib files which it rootViewController , SecondViewController and mainview.
So the problem is:
When i try to executed didSelectrow in rootViewController and access the NSMutableArray *array in SecondViewController and replace the *array value with new array value in rootViewController before pushed animation.
The array value on my SecondViewController was changed for the first time but when i pushed the back button and select the other row, my SecondViewController array kept read the previous array not change to a new one. I try to initialize but no luck
This is my code on rootViewController UITableview (didSelectRow):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(2ndController == nil)
2ndController = [[DetailViewController alloc] initWithNibName:#"SecondViewController" bundle:[NSBundle mainBundle]];
//Declare xml NSMutable array record
ListRecord *record = [self.entries objectAtIndex:indexPath.row];
//access SecondViewController NSMutable *record
2ndController.record = [[[NSMutableArray alloc] init] autorelease];
//inserting the value from firstview to secondview before push
2ndController.record = record;
//push animation
[self.navigationController pushViewController:2ndController animated:YES];
}
This is my second view controller :
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
switch(indexPath.section)
{
case 0:
[cell setText:record.name];
break;
case 1:
[cell setText:record.Age];
break;
case 2:
[cell setText:record.summary];
break;
}
return cell;
}
Hope someone can help me..
Thanks in advance.....
Few things,
You do,
2ndController.record = [[[NSMutableArray alloc] init] autorelease];
and follow it up with
[cell setText:record.name];
Clearly, the record property doesn't seem to be an instance of NSMutableArray so I think the array initialization part is incorrect as you do, and already mentioned,
2ndController.record = record;
But the problem I think is that you are retaining your UITableViewController subclass. Have you tried reloading the data?
[self.tableView reloadData];
Add it in the viewWillAppear method of your DetailViewController.
You should look at these two lines again:
2ndController.record = [[[NSMutableArray alloc] init] autorelease];
//inserting the value from firstview to secondview before push
2ndController.record = record;
The first line doesn't do anything useful for you. It creates and initializes a new NSMutableArray and sets the record property to that new array.
But then in the very next line you set the same 'record' property again to a different object and so that array in the first line is no longer referenced. So you might as well not have ever created it.
That's not your issue exactly, but this comment was too big for a comment. :)