iPhone/Obj-C - Archiving object causes lag - iphone

Hi I have a table view, and when I delete a cell I am removing an item from an NSMutableArray, archiving that array, and removing the cell.
However, when I do this, it is causing the delete button to lag after I click it. Is there any way to fix this?
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
int row = [indexPath row];
[savedGames removeObjectAtIndex:row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//this line causing lag
[NSKeyedArchiver archiveRootObject:savedGames toFile:[self dataFilePath]];
}
}
Thanks

It sounds like you know the answer already -- don't archive everything on every delete. This can be done a number of ways -- archiving only pieces at a time, delayed archiving (periodically/when quitting/other policies), or making your custom archiving code considerably faster, which I doubt would even help that much in the scheme of things. I've heard that MAKeyedArchiver was faster than NSKeyedArchiver, but I believe this was some time ago, and designed for the mac+potentially platform specific (on the bright side it was intended as a drop in replacement for the NSKeyedArchiver API of the time, so it should be little integration time if you choose to use it).

Related

cellForRowAtIndexPath Usage Pattern

In the below code I want to perform some DB actions when a cell is deleted, therefore I need to send my Server information about the cell being deleted. If I remember correctly cellForRowAtIndexPath should never be called directly, However I cannot think of any other way to get cell info in the below method, so my question is:
Is it acceptable to call cellForRowAtIndexPath manually below:
[tableView cellForRowAtIndexPath:indexPath]);
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[localGlobalNotifications removeObjectAtIndex:indexPath.row];
[notificationTableView beginUpdates];
[notificationTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[self postLeaveRequest];
NSLog(#"Row is : %#", [tableView cellForRowAtIndexPath:indexPath]);
[notificationTableView endUpdates];
}
}
To clarify: I understand that I can invoke a delegate call of cellForRowAtIndexPath by calling reloadData, what I'm trying to do is access the cell being deleted within commitEditingStyle. I'm not trying to reload my tableView, instead I want to get a reference to the cell being deleted. - Is it acceptable to obtain a reference to said cell by calling cellForRowAtIndexPath directly?
There's nothing wrong with asking the TableView to give you the cell, just as you do in your sample code.
Here's the documentation for the return value:
An object representing a cell of the table or nil if the cell is not visible or indexPath is out of range.
If you're annotating the cell with 'model' data then I think you're breaking the MVC pattern. Your view doesn't need to know about the model data in this way, and so querying the view to make a database change will make life difficult you in the future (readability, extensibility and reusability for example)
You would be better off having your DB metadata stored in a collection such as an NSArray - or an NSArray of NSArrays.
Then you could get all the data you need with something like:
id modelData = myModel[indexPath.section][indexPath.row];
Yes you can use cellForRowAtIndexPath: as they have also used in apple docs or you can create an array of your cells then you can delete it from there and reflect it in your database.
You can call cellForRowAtIndexPath: method using following line, here it will automatically calls all delegate and datasource methods.
[tableView reloadData];
or
[tableViewObjct reloadData];
Hope this solves your problem!

Flushing UITableView queue for cells

I was wondering if some one can please reply me with if the UITableView queue gets flushed when UITableView reloadData is called.I am trying to do so and this isnt helping me.Any suggestions?
if you look at the header file for UITableView, you can see that there is a private NSMutableDictionary (iVar) called "_reusableTableCells". This is a dictionary with cell reuse identifiers as key and with array with cells that are currently offscreen as value.
If you want to manually flush queued cells in way that may change with the implementation, you can do so in ugly manner, like so:
NSMutableDictionary *cells = (NSMutableDictionary*)[self.tableView valueForKey:#"_reusableTableCells"];
[cells removeAllObjects];
Hope this helps...
Once the table is loaded, the cells are reused. Reloading the table does not flush the queue. reloadData calls - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
In this method the if(cell==nil) condition is present so that cells are not flushed once they have been loaded into memory, and therefore reused.
To get around this you reset your cells before applying the correct information.
cell.detailTextLabel.text = #"";
cell.accessoryType = UITableViewCellAccessoryNone;
Or if you are using an accessoryView
cell.accessoryView = nil;
Also take a look at this example. UITableView not updating correctly when scrolling.

NSMutableArray to table view

i am new to the iPhone development.
i need to display the NSMutableArray contents into UITableViewCell..
it is quite simple.. but, i want to know, how to add the NSMutableArray contents into table view at runtime?
please anyone help me..
thank you very much..!
Have you read the Table View Programming Guide?
In particular the section that talks about Creating and Configuring a Table View.
The little code snippets on those guides provide examples that deal with the simplest case, which is an array.
In short, you provide a "data source", which the table view asks for each row from. That data source is usually (but doesn't have to be) the ViewController that uses the table.
Make sure to check out the example applications linked to there if you need to see some working examples in Xcode itself.
You want to add total array to single cell or a tableView. If the answer is tableView, then you can directly give the values in the following method like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
cell.textLabel.text = [array objectAtIndex: indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
}
you can use like that.

Why does this line indefinitely repeat?

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCellFixed *cell = (UITableViewCellFixed *)[tableView cellForRowAtIndexPath:indexPath];
the second line (ie: the first line after the function is declared) is repeating itself indefinitely. I have no idea why.
I got a stack overload when I was running the script, and when I put a breakpoint on this line and subsequent lines in the same method this line just continuously repeats and the breakpoints never move onto the next one.
I have no idea why this is, but this is my first time trying to subclass a UITextViewCell, so I'm assuming I've done something wrong?
Thanks
Tom
When you ask your table for a cell, the table itself calls heightForRowAtIndexPath to be able to display the cell in correct height.

How to delete table rows programmatically?

I have a table which I am manipulating with a tableViewController (no nib, and the controller is creating the table behind the scenes)
I'm trying to delete a row from the table based on its row number; I can delete it from the array I use to create the cell in cellForRowAtIndexPath, but I get a strange error if I try to do the following, which is the same code as in tableView:commitEditingStyle:forRowAtIndexPath:
where it works fine
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i+1 inSection:1]
[self.tableView deleteRowsAtIndexPaths:[NSArray
arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
It gives an error
-[_WebSafeForwarder forwardInvocation:]
and then jumps out of the method but does not crash the app
Can anyone help?
You need to do that in this block.
[self.tableView beginUpdates];
///
[self.tableView endUpdates];
do notice one thing that when the the block reaches its end
- (void) numberOfRowsInSection:(NSInteger)section
will be called again. so u need to update the number of rows in table view also.
Hope this helps.
Thanks,
Madhup
Well you are missing a semi-colon on your first line.
When in doubt, clean up your syntax...
As a point of observation, most of the programmers I have worked with and talked to really hate UITableViewController. It really adds nothing to the functionality for the user and only obfuscates things that developers might really like to control... such as the position of the table via a XIB.
It's just a convenience class and in my experience, causes more issues than it prevents.