My iPhone app has a sub view on its Welcome View Controller. The sub view parse data from a website and load data accordingly. Welcome View Controller has a continue button to go to the next view controller. But until the sub view load its data I cannot go to the next view controller.
Can anyone suggest me any solution on this. Thanks in Advance.
In you are using NSURLConnection/NSURLRequest to retrieve the data, I would suggest two approaches:
modify the code your class that retrieves the data so that the request is made asynchronous; this will make it non-blocking and the user will be able to move next without waiting; when moving next, you'll have the option of canceling the request, so to save bandwidth;
perform the request in a separate thread; you can do that either using NSTask or GCD dispatch_asinc like shown below; in this case anyway, you have to be aware of the fact that your separate thread may not modify the UI (i.e., use UIKit), because this can only be done from the main thread. So, in your thread, you update the data, but then issue a refresh of the UI on the main thread (by using performSelectorOnMainThread).
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ [self SENDREQUEST]; });
As Vince pointed, you should retrieve the data from a separated thread (create a worker class to do that for you). When the classes finishes his job, you should tell the Welcome view, that the data is ready. You could achieve that, by using a protocol, or NSNotification.
Related
I'm doing an app that uses a TabBarController and each Tab uses its own navigation controller.
The app has dynamic content and I use viewDidDisappear viewDidAppear methods to create or destroy the objects that I need each time I enter or exit into the ViewController.
My problem is when I start to sail very fast and I don't give time to load the Threads that I use for uploading content such as XML peta app or destroy objects when I leave the ViewController.
How I could control the tabs of the navigationbar or tabbarviewcontroller for not respond until the viewcontroller has loaded all contents?
Excuse me if I'm not well expressed. Thanks!
No matter you use synchronous request or asynchronous request, just show an UIAlertView while loading the data. This will both serve as a notification to the user that something is being loaded, and the it will block the interactions with all the other views on the screen.
As others have suggested in comments, I believe that what you want to do is rearrange the order in which things are triggered. Perhaps something like this:
On viewWillAppear:, clear (or disable or whatever is appropriate) your objects that are no longer valid and begin the load-new-content thread. Perhaps display a UIActivityIndicator or similar.
On viewWillDisappear:, tell the load-new-content thread that it can stop, its results are no longer needed. If you put up an activity indicator, take it down.
At the end of the load-new-content thread, take down any activity indicator, update the UI with the new contents and activate.
I don't really see any way around this -- if the UI is not valid until the new content is loaded, then you have to wait for it.
Another solution might be to cache the contents from the previous fetch, and always display those on viewDidLoad. Then, at the end of your new-content-thread, cache the new contents, and update the UI.
I've been trying to implement this for a long time and I have gotten no favorable results.
Say I have a method in the which an HTTP request is performed (specifically, a twitter update), and say I want to display a UIActivityIndicatorView while the HTTP request is in progress (I know when it is done because there are delegate methods that are called when the request is done, either with positive results or negative ones).
I've seen many answers that say that threading is necessary for the implementation of this class. At first I tried calling the startAnimating method in a different thread and the stopAnimating method directly (without starting a new thread). After that I saw how this guy does it and I thought this was safer as I was starting and stopping the indicator in two different methods (the delegate methods for the twitter update).
However, none of this two ways of doing this have given me the results I want (the activity indicator does not show up at all). Is there anything I'm missing?
Thank you in advance and I apologize if my question is too long.
Your help is very much appreciated.
Threading is absolutely forbidden when working with UIKit subclasses. You may have seen reports that UIActivityIndicatorView uses threading internally, but in no way does that mean you can access the object from multiple threads. All UIView subclasses (including UIActivityIndicatorView) must only be accessed from the main thread. This includes calling -startAnimating and -stopAnimating.
If you rewrite your code such that you're only ever accessing the activity view on the main thread, and it still isn't working, then I would guess that the view was either not added to a visible view, is covered up by another view, or has a frame that puts itself outside of the visible area of its superview.
You cannot perform UI stuff in a secondary thread.
You should perform your HTTP request in a secondary thread, while calling the activity view from the main thread.
I recommend using DSActivityView which is so much easier to use. Just 1 line to show an activity view, 1 line to hide.
MBProgressHUD it's also easy and shows and hides itself when the secondary thread has started/finished. Something like this:
[HUD showhileexecuting:"yourstuff" animated:YES]
"Yourstuff" will run on a separate thread.
You should not perform UI activities in a secondary thread.
I am trying to load a table view from a cache very quickly and have the cached data in the table view appear. Then I want download new data, and then reload the table. Right now I am downloading the new data on viewDidAppear, but the view still refreshes before it displays. Any idea how I can do this?
viewDidAppear is not a good place to download data; it is really intended for clean up after presenting data, so I can understand why you used it. You should request your data reload as early as possible, such as in viewDidLoad or viewWillAppear (depending on your reuse or otherwise of view controllers).
If you are doing asynchronous downloads, which you should be, put the reloadData call in your delegate callback function for when the data is completed.
Simply calling [tableView reloadData] after the download might do the trick. This will trigger a refresh of your table cells.
To download the new data, you may consider using Cocoa Streams, particular an asynchronous Socket Stream. In the stream delegate, call reloadData when the download is completed.
I ended up implementing the delegate class to do this asynchronously. This example was extremely helpful, and I implemented much of its code:
http://developer.apple.com/iphone/library/samplecode/URLCache/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008061-Intro-DontLinkElementID_2
I am creating a tabbar application. One of the tabs is for an rss feed, which is a navigation application. but when i click the tab bat button, it is taking a while to load the view of that tab. It is because the application is waiting for the feed to be loaded from the server. Is there any way to load the view before the loading of that feed takes place. As of now, i'm giving the request in the viewDidLoad method. Thats what is creating the problem. To which part shall i move the code so that the view is loaded instantaneously when clicking the tabbar button.
I recommend this great article on this subject on iCodeBlog, it's a very elegant way of doing this. If you submit your rss feed loading as an NSOperation, it will take place nicely in the background without blocking your main thread.
use:
[self performSelector:#selector(performRSS:) withObject:<nil afterDelay:0.3f];
or
[NSThread detachNewThreadSelector:#selector(performRSS:) toTarget:self withObject:nil];
and place RSS feed related code in a separate function named "performRSS".
I also think that the problem is more that you don't use the HTTP request asyncronously (as Apple recommends). See this document. http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
It worked for me in my applications.
I am working on a an application which is very simple
a navigation controller with a table view
when the user clicks a row, he is directed to the details view.
However, the details view pulls data from Core Data. i am pulling a relatively large amount of data that takes about three seconds to load.
I wanted to add that UIActivityIndicatorView to show progress.
I tried to start the animation once the user clicks the row, so i set it to animate in didSelectRowAtIndexPath
For some reason, the Activity Indicator doesn't start before the pushing of the details view.
Any idea why? or the best way to implement such an idea?
~Adham
Because you start the animation and then start a large operation in the same thread. Consider running that 3 second operation in a new thread. Look at NSOperationQueue and then create a NSOperation to run that procedure. It will work this way.
The UI doesn't update until the end of your run loop. You are, in sequence, displaying the activity monitor, then pushing the new table view, and then the UI updates. You need to change this order.
You can either move something to a different thread, or you could perhaps delay the loading of the new table view by calling performSelector:afterDelay: with a delay of 0. That will delay the loading of the new table view until after the activity indicator appears in the UI. Now, it's still all on the same thread, so you will be blocked from doing anything, but if the animation is threaded in the activity monitor, it would make for a quick and easy solution.
Call method in thread:
[NSThread detachNewThreadSelector: #selector(loadMethod) toTarget:self withObject:nil];
See following for more details:
http://iphone.zcentric.com/?s=UIActivityIndicatorView