slow pushing when a tableview element is selected - ios

In my app,i am using tableviews, populated through XML parsing, i get my XML from an ftp, the XML contains other xml urls for the next views and images urls and text, the problem is when an element of the tableview is selected it pushes to another view, But load for a very long time.
I run my app into the simulator, i never tested it on a device.
does anybody knows what may be the problem?
Is it a connection issue?
will it work fine on a device?

I would suggest testing your code on a device and not making assumptions about the peformace. I assume you are going to the server and ask for those images to display in the pushed view. In which case you should load the view with image placeholders and spin off the downloading images in a secondary thread (good habit for slow loading as to not block the UI) and update the image placeholders as the image data become available.
I will gladly update this answer if you need more specific help.
If you are loading a tableview in your pushed view, the hang will happen on the view before that pushed view (that is very terrible UX). So move the logic of the code that take a while into the subclass of the "pushed view", you can implement something like a spinner (I use MBProgressHud) while you crunch you data. This way you will get the view loaded before the lag begins.
Now the flow to improve UX can be as follows:
1. In the - (void)viewDidLoadof the pushed view you can hide the tableview (or not).
[self.myTable setHidden:YES];
2. In the -(void)viewDidAppear:(BOOL)animated of the pushed view throw up a spinner for the user to know you are doing work (work here being going to the server to look for the images from the urls) and do the work.
//your code here will vary
3. When you know that all your data is downloaded just load the table, hide the spinner and show the table. You can do this at the end of the -(void)viewDidAppear:(BOOL)animated method.
[MBProgressHUD hideHUDForView:self.view animated:YES];
[myTable reloadData];
I recommend sending all the expensive work into a secondary thread, because a user would hate to decide not to wait and have a blocked back button in the navigation bar. But for to answer you original question you pushed view should load immediately, but then wait to get the data.

Related

swift segue new viewcontroller stuck when other tasks loading on background

Currently, I have a UItableview which loads based on API. And when clicking on a cell, it segue(show e.g.push) to another viewcontroller. It displays all the cells after the first API call, then it calls other APIs and loads other data(which takes a while and also uses cpu heavily), but the scrolling seems to be smooth when loading.
However, when not fully loaded, if I click on a cell and the other viewController pops up, the entire app freezes for a moment. (The new viewController has all the content displayed, just not responsive)
Is there a solution for this?
What I can think of right now is to decrease the CPU load by loading fewer cells at a time.
Typically you are not going to want to do this:
"loads other data(which takes a while and also uses cpu heavily)"
The better solution would be to not call your second call to fetch all the data and just fetch the data needed to show on your next view controller you are segueing to. Typically done by passing an ID in your API call. So on your tableviews didSelectRowAt you would make the api call to get your data needed that is specific to the next screen, then segue.
If this is not possible due to server side limitations, then you are going to want to chain your first two calls. Meaning don't even show the table view cells until you have all the data.

Show activity indicator while changing views (Segue) and load data for next view (API)

Umm I really need some help
I have a search view, when user clicks the cell (basically a game), the view changes to a Game View. Atm I was not using any async stuff so while the game view loads, the app kinda hangs for 2-3 secs on the search view after clicking the cell (since the viewDidLoad method of game view loads all data from web API)
What I wanted to do was when a user clicks game in searchView, the gameView instantly shows up with just a blank view and a Activity Indicator meanwhile the data is fetched from API.
Once data is fetched, the gameView (which is a tableView btw) reloads the data and shows it accordingly from the fetched data.
If it makes any diff. I am using static cells for gameView and thus not using cellAtRowIndex code.
I have attached images for some of my methods I tried to use as per my searching on SO for AFNetworking, async etc etc.
The table IB elements are filled from data in a separate function showGame, I am calling this function in rowsForSection since table will be reloaded after block completion. Excuse me but I wasnt sure what would be the best way to reload table or rather show the data.
Atm my app is showing me my default static content which I created in interface builder (and with only 1 row). AKA the table is not being updated. I used breakpoints to check and yeah the showGame is getting correct data, passing correct data to IB elements. Even the execution is reaching the point in code to return 5/6 rows BUT the actual app/view is not updating properly.
For those who want pastebin text code, here it is:
.m file where async code to fetch game from API is
http://pastebin.com/p2FETbku
.m file of my gameView class/tableView which shows the table view and data, this file also has the showGame method to show the game data fetched from above class
http://pastebin.com/cWtSKPw0
Please excuse my code or any small mistakes, I am still in learning phase and just started 3 weeks ago.
The static cells were working fine before I was using async method, somehow its getting messed up during/after that reloaddata
One point that I think you are missing is that execution of this statement
GDgameViewController *gdv = [[GDgameViewController alloc] init];
doesn't return the tableViewController hence the tableView that is currently presented.
So in your function +(void) fetchGame:(NSString *)gid what you are reloading is the tableView that is not presented.
To help you further I have created a project for you which use a bit different approach to do your work but it does it optimally. You can find project here. If you don't know how to use gitHub, don't worry just download the zip file. Please make this count as

Web services data is coming late and table view is empty

I am new to ios sdk, working on app which includes web service calling and parsing JSOn.i have two view controllers on first view i am calling web service on button click and in second view i have to display all record in table view. everything working well , parsing values are also coming properly. but values are coming late and table is displaying empty values. but when i am navigating back and coming again then it will display all button.How to handle this situation?
The beauty of Asynchronous download is making things ready for us in other than main thread. All UI components gets updated by Application main thread, In your case TableView UI updating on main thread and downloading happening in separately. I guess only thing you might missed here is, after downloading finished not getting the notification. Once you arrange notification after downloading process finished, just update your tableView by calling [tableviewobject reload];. Which ll done all reloading of the tableview(this is nothing but refreshing all tableview again). Good luck.
Are you reloading the table view once the data has been downloaded?
Something like this in your Table view controller:
[self.tableView reload];

Images not loading FIRST time a UIWebView is used

My original plan was to use a split view controller to have a table view and a generic view beside it for an iPad app. Then I realized I could not use a split view controller as a child controller. So, I've been experimenting with using a table view controller instead, and I've got pretty good results so far. Essentially, I'm using the tableview's header view as a container for the various views I'll be using depending on which row is selected. The only unresolved issue is that images for a website are not displayed in the UIWebView the first time it is presented. If I tap another table row that displays a web view, it displays fine. And if I tap the original one again, it displays fine, too.
It doesn't matter which one I tap first. It's always the first one that doesn't display images. Instead of displaying the images, it displays the names of the image files.
When I tried the analogous thing with a split view controller, I didn't have this problem.
Any ideas what I should be looking for? Or is there something I need to be doing that I must not be doing?
If it matters, the page being loaded is just a thumbnail page on a remote server, created with Irfanview's HTML thumbnail page generator.
P.S. After further testing, it is really the very first presentation only that doesn't work as expected. By very first, I mean the first per app session. The UIWebview is presented as a subview of the table header. The tableview controller is presented as a popover from a button of another controller that is presented when a user taps an image. Even if I dismiss all these layers of controllers, etc., if I instantiate them again, the UIWebView displays properly.
This suggests possibly loading a dummy UIWebView before starting, but that seems kludgy.
I'm getting exactly one call to webViewDidStartLoad: and exactly one call to webViewDidFinishLoad: and no calls to webView:didFailLoadWithError:.
KLUDGE:
The kludge works. Here it is:
In my table view controller, I create a boolean property URLHasBeenRequested and set it to NO in viewDidLoad. Then I ask for a reload thus:
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
if (!self.URLHasBeenRequested) {
//On first pass, try a second request.
[webView loadRequest:webView.request];
self.URLHasBeenRequested = YES;//Set this flag so a duplicate request happens only the first time.
}
}
I suspect this has more to do with the way the UITableView is loading the header and trying to allocate memory during that process, than with the UIWebView itself. For whatever reason, the UIWebView's loading seems to be getting interrupted while the rendering of the UITableView is still finishing ( just a guess ).
One thing you might try would be to go ahead and setup your table header by adding the UIWebView subview, but not calling "loadRequest" right away. You could, for example, wait until the rest of the visible cells of the table have been loaded, and then load the header view last. You can detect when that occurs like this:
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
[webView loadRequest:webView.request];
}
}
This is, admittedly, also a somewhat kludgy workaround, but at least you're not having the UIWebView load the content twice. I also haven't tested this myself, and without seeing your actual table loading code, it's hard to say if the root of the problem lies somewhere else, but let me know if this works!

Performance issue when reloading tableview section

When new data is received by my app, a notification is sent out and received by my view controller. The view controller then reloads one of the sections of its tableview. This typically takes just 40ms or so.
However, if I have pushed another view, the notifications are still processed by the original controller but the reload of the tableview takes about 10-20x longer.
I can certainly work on improving my tableview performance, but first I need to understand what is causing this. Would also appreciate some help using Instruments on how to debug this myself. So far I have run the 'Time Profiler' instrument and it looks like most of the effort is expended in system method, '[UIView(Hierarchy) layoutIfNeeded]'. This doesn't mean much to me.
You definitely don't need to be updating UI on an element that isn't onscreen. UI updates will take place in the main thread, which will negatively impact user experience.
Updating your data source (in a background thread) should be more then adequate, and then you can update the tableview when it is next shown to the user.

Resources