How to know when moving row is done - iphone

My app allows user to reorder rows in a table view, but I want to reloadData after moving is done to change something (add some text to the first row).
I tried to reloadData in moveRowAtIndexPath: method, but it makes the app hang because this method is called many time (according number of rows need to be moved) and the table view is reload many time.
So, I just want to know when the moving behavior is done then I reloadData in just one time. Does anyone know about this? Please help me. Thanks you so much!

- (void)doReload
{
[myTable reloadData];
}
You can do [self performSelector:selector(doReload) withObject:nil afterDelay:0.1] in the moveRowAtIndexPath method but you can't call [myTable reloadData] directly because as you found it causes a loop. Basically you need to allow the table manipulation to finish and the run loop to get around to calling your method which then causes a reload of your table. This is a bit of a hack but it works well. Ordinarily you don't need reloadData at this point but you may be trying to do something out of the ordinary.

-(int)table:(UITable*)table movedRow: (int)row toRow: (int)dest

Related

How to implement a uitableviewcell who's value is derived from another uitableviewcell

I'm trying to do something thats fairly simple but I can't see the best way to do it. I have a uitableview with two cell's, the first has a uitextfield in the contextview with the input view set as uidatepicker. The cell maps back to a nsmanageobject date property. The nsmanagedobject has a dependent property which is the difference in days between todays date and the date selected. This value is displayed in the second cell when the view loads.
The problem is that when the user changes the date in the first cell the second cell is not updated automatically.
Firstly I thought I could just call setNeedsDisplay on the uitableview. But this seems rather heavy handed.
So I've been reading up on KVO and I've not managed to find a good example of a solution to my problem yet.
I'm using fetchresultscontrollers for my tableviews. I tried to implement a key path dependency as shown in the iPhone docs but this hasn't been successful.
for example...
+ (NSSet *)keyPathsForValuesAffectingDaysRemaining
{
NSLog(#"keyPathsForValuesAffectingDaysRemaining");
return [NSSet setWithObjects:#"dateOfOccasion", nil];
}
-(NSNumber *)daysRemaining {
return [self.dateOfOccasion daysFromNow]; //simple calendar calc.
}
Could someone point me in the right direction of an appropriate solutions to a relatively simple problem.
Thanks,
Gary
I think implementing a [[self tableView] reloadData] strategically should fix the problem. As soon as you change the object in cell1, I would assume you basically save the change globally or in Coredata. Simply reloading the tableView in that configuration should fix the issue.
In your case, since you are implementing the NSFetchedResultsController , I would assume objectDidChange would fire when you change the value of that object. A tableView reloadData would be a nice implementation there !
If you have the modified value , you could reload the row to update the content. You can reload row in your KVO method after updating row's value,
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);

Should I clear table view before using reloadData?

I want to put new values in a table view.
My tableView:cellForRowAtIndexPath: has the following
if (cell == nil) { // do something }
When I remove the if statement on top and use reloadData the app crashes. Do I need to clear the old values in the table before I use reloadData? If so how?
Thanks
Edit:
I'm sorry i didnt mean that i put reloadData inside tableView:cellForRowAtIndexPath:. i put it inside another method and removed if (cell == nil) { // do something } from inside tableView:cellForRowAtIndexPath:
You should read the TableView Programming Guide to familiarize yourself with the concepts. reloadData is a method that eventually calls tableView:cellForRowAtIndexPath:.
You are generating infinite loop by calling reloadData inside
tableView:cellForRowAtIndexPath:
There is no need to clear data in a table view. You may want to ensure you properly implement -prepareForReuse in your UITableViewCell subclasses though, so that reused cells don't show old data.
It's BTW unclear why you want to remove the if (cell == nil) bit. If there is no cell to reuse (dequeue) then you need to create a new one. If you don't you'll return nil, which will cause an exception in UITableView.
You (99% of the time) can't call reloadData from tableView:cellForRowAtIndexPath:.
This is because reloadData eventually calls tableView:cellForRowAtIndexPath, so you get a never ending loop.
You need to explain more what you trying to do (and some extra code would be nice) in order to answer the question further.
reloadData calls all tableView data source , so you cann't call it in cellForRowAtIndexPath it will make an infinite loop.

UITableView performance issue

I have a UITableView which gets data from a server and updates in every 1 second(using performSelectorOnMainThread). Since this blocks main thread sometimes its not easy to scroll the table and its painfull for the user. Also i cant reduce my refresh interval also.
What are the possible solutions for this problem?
I would only refresh the visible cells as the data changes, and the others as they appear so it will be less consuming than updating the hole UITablaView
you can get the visible cells using ( from UITableView):
- (NSArray *)visibleCells
and you can update the remaining cells as they appear using UITableViewDelegate Protocol
– tableView:willDisplayCell:forRowAtIndexPath:
and i think this should make it a bit faster.
Hold your data in a mutable array or similar structure then asyncronously update that array with an NSURLConnection. You can call reloadData on the tableview to redraw the table when the NSURLConnection is done.
You would probably just call the NSUrlConnection from an NSTimer at whatever interval you prefer.
instead of calling performSelectorOnMainThread function of NSThread call
detachNewThreadSelector function. In this way your thread will not block the main thread
[NSThread detachNewThreadSelector:#selector(aMethod:) toTarget:[MyObject class] withObject:nil];
in toTarget: method you can write self instead of [MyObject class]
also in Implementation selector write #synchronize(self) for eg.
-(void)aMethod
{
#synchronize(self) {
//write your whole code here
}
}
I have done the same thing in my application its work perfectly
Use GCD with queues (serial or global queues). This is the apple recommended way now.
dispatch_async(dispatch_get_main_queue(), ^{
//do UI updates
});

How to tell a UITableView to preload all Rows?

Is there a way to tell a UITableView to preload all rows?
The tableView is supposed to show several comments (up to 80 comments).
So my CommentCell uses a Setter to adapt the cell to a specific comment.
-(void)setComment:(Comment *)newComment {
if (newComment != comment) {
[comment release];
comment = [newComment retain];
/*
* set the cells view variables here
*/
}
}
This specific setter takes quite a bunch of processing resources and scrolling gets kinda laggy.
I am using a comment-specific reuseIdentifier instead of a static cellIdentifier when calling
dequeueReusableCellWithIdentifier:
in order to assure, that "newComment" equals the old "comment".
And in fact this does work great when scrolling over cells which have already been loaded.
But when scrolling through the comments for the first time, it still lags like hell.
Which leads me to my question:
Is there a way to tell the tableview to preload all cells? (which I doubt)
or
Do I have to implement my own cache instead of relying on "dequeueReusableCellWithIdentifier:"?
Keep in mind that your comment specific reuseIdentifier could be what is causing everything to go slow (or at least, it isn't helping). The reason we use reuseIdentifier for UITableViewCells is because if you try to allocate a new cell every time you need one it isn't as performant as if you can just reuse one that was already made.
I'd recommend pre-computing your comments so you can just set properties of your cells and reusing cells after they scroll off the tableview.
No, you have to preload your data in your dataSource. Just put everything you need in an array and fill the table's cells from that array of preloaded objects.

Can I show/hide a certain cell in an UITableView depending on the state of another cell?

I have a UITableView with style "Grouped" which I use to set some options in my App. I'd like for one of the cells of this UITableView to only show up depending on whether another of this UITableView's cells is activated or not. If it's not, the first cell should show up (preferably with a smooth animation), if it is, the first cell should hide.
I tried returning nil in the appropriate -tableView:cellForRowAtIndexPath: to hide the cell, but that doesn't work and instead throws an exception.
I'm currently stuck and out of ideas how to solve this, so I hope some of you can point me in the right direction.
You should remove the data behind the hidden cells from the table view's data source.
For example, if you are using an array, when an action occurs that causes a cell to be hidden, you would remove the object for that row from the array. Then, as the table view's data source, the array will return one less total count and only return valid cells for every row in that count (no nil).
This approach may require maintaining a second array with all of the objects (including hidden).
To update the view, check out reloadRowsAtIndexPaths:withRowAnimation:.
Here's a handy post in which the author provides some source code for performing animations on the currently selected cell:
http://iphonedevelopment.blogspot.com/2010/01/navigation-based-core-data-application.html
He's using this in a NSFetchedResultsController context, but you can see how he's using various calls to add/remove cells & sections.
Now, in your case, you'll need to modify whatever array you're using to host the data used to generate the rows in your tableView when you "activate" your cell, then selectively use:
tableView:insertRowsAtIndexPaths:withRowAnimation:
tableView:deleteRowsAtIndexPaths:withRowAnimation:
tableView:insertSections:withRowAnimation:
tableView:deleteSections:withRowAnimation:
to adjust things accordingly (you can start with tableView:reloadData:, but it's inefficient).
I realize that the API can be a bit daunting, but take the time to read through it and understand what the various calls do. Understanding how the UITableView uses its datasource and delegate, as well as the chain of events that occur when cells are selected/deleted/etc., is important if you want to get things just right (and crash-free).
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:withRowAnimation:]; // or insertRowsAtIndexPaths:withAnimation:
[tableView endUpdates];
Before cellForRowAtIndexPath is called, numberOfRowsInSection is called. You should return the appropriate value of cells in the section there, so if you only want to show 1 cell, return one. The logic what cells are shown has to be implemented partially in both methods