i have one view ,in that i want to show table view with mapview .
my problem is how can i process in both thing same time. i want to show this things same time so speed problem not come.
for more info i added image which i want to show.
You'll want to look at multithreading my friend.
Have your methods that manage the tableView run in one thread, and the map methods in another.
For instance, in your viewDidLoad:
[self performSelectorInBackground:#selector(downloadMap) withObject:nil];
[self performSelectorInBackground:#selector(downloadTableData) withObject:nil];
Related
I know how to animate,display the Activity Indicator.
But I want to know how to immediately show the Activity Indicator.
Now When I am click the button it will load another view after 5 or many seconds. Clicking that button is loading a subview. When that Button Click method is called, it will call more than 7 methods after that and then it will load the subview. But the ActivityIndicator is displayed only after it complete executing all the 7 methods.
What I am trying to do is , I want to display the ActivityIndicator immediately after that Button Click method.
Any Idea ?
-(IBAction)button_click{
..
..
..
[self performSelector:#selector(afterDelay) withObject:nil afterDelay:0.3];
}
-(void)afterDelay{
YOUR_Code
}
The problem is that you perform your massive calculations (or loading from the internet?) on the main thread, but all the view mutation operations are not called immediately — on the start of the runloop the framework creates a new implicit Core Animation transaction, then it collects all the information about views' mutations, then commits the transaction on the end of the runloop. By blocking the main thread you are not allowing the transaction to commit and start your indicator's animation.
You can read about this architecture in the documentation: Core Animation Programming Guide: Transactions.
There are three options:
(Preferred) Perform your operations on the background.
Link your binary against QuartzCore.framework, then #import <QuartzCore/QuartzCore.h> and call [CATransaction commit] after your startAnimating call. This way you commit the implicit transaction.
Create your own explicit CATransaction.
If you have put the code to display or unhide the activityIndicator but it is not shown you have to use performSelector:withObject:afterDelay: method for doing any thing after unhide or displaying the activityIndicator with the delay of 0.001 will show the indicator immediately after clicking the button
Happy Coding :)
If your are talking about the system activity indicator, use this :
[[UIApplication sharedApplication] performSelector:#selector(setNetworkActivityIndicatorVisible:) withObject:[NSNumber numberWithBool:YES ] afterDelay:0.0];
I have an iPhone app that starts in a table view and goes to a different table view when the user selects a cell. The two table views are in separate classes (or whatever the proper Objective-C term is, ie. 2 different .h and .m files), and the second table view makes a request from a server based on the selection in the first table. There is a noticeable delay and I've been trying to put a UIActivityIndicatorView up when that happens, but that only displays for a split second when view segues to the second table view. I know this is an issue with threading, but I can't get this to work following any of the other posts on this topic. I call my startAnimating in didSelectRowAtIndexPath and the stopAnimating in the viewDidDisappear. I have also tried using the following code to get this to work by calling it in the didSelectRowAtIndexPath: [activityIndicator performSelectorInBackground: #selector(startAnimating) withObject: nil]; How do I make the activity indicator (or any loading animation for that matter) to work when the server request is going on?
I see that this is a frequent problem on Stack Overflow, but I did just find a working solution. I found this forum iphonedevsdk.com/forum/tutorial-discussion/… My issue was a synchronous connection taking up my main thread, so starting the spinner and then calling the connection in a separate method does the trick.
I have a two views, 1st is a simple view with some introduction about usage and by click of a button it opens the main view. The main view has many images and two customized tables with rows consists of text and image, thus the creation of the main view is quite slow. The profiler shows most of the time is consumed by imageIO (decode_mcu, png_read_filter_row, pmap_copy_page and decompress_onepass)
I want to optimize by creating the main view immediately after the 1st view is loaded, and when I click the button, it simply set that view to visible or bring that view to front.
I tried to alloc & init the main view in the first view's viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
rootVC = [[RootViewController alloc] initWithNibName:#"ViewController" bundle:nil];
rootVC.delegate = self;
}
and do this in the button's action method
- (IBAction)buttonUp:(id)sender {
[self.view addSubview: rootVC.view];
}
But this is not working, the loading still takes very long. How could I sacrifice some memory to make better user experience?
Thanks
Leo
You should:
Use Instruments to see where your code is spending the most time, and optimize there. It may not be where you think.
If you are using a UITableView, learn how to create UITableViewCells on demand (rather than preloading a large number) and recycle instances (rather than recreating them).
Only if Instruments points to this as the bottleneck: try loading/decompressing images in on a background queue, then updating the UIImageView (or whatever) on the main queue after loading.
In iOS 4.x or later, you can do this:
NSString *path = ...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
// This is happening in the background thread.
UIImage *image = [UIImage imageWithContentsOfFile:path];
dispatch_async(dispatch_get_main_queue(), ^{
// This is happening on the main thread; all UI updates must happen here.
imageView.image = image;
});
});
P.S. By the way, UIViewController doesn't load the view on creation, but on demand. So based on your code above, the expression rootVC.view is probably triggering the view to load. If you want to force it to load earlier, just put rootVC.view somewhere else.
UIViewController tries to load its view lazily, i.e. the view isn't loaded until it's actually needed. If you really want to force your view controller to load its view, you just need to access its view property, e.g. rootVC.view.
However, you really shouldn't need to do that. Table views, for example, only create the cells that are visible on screen, so it's unlikely that the number of rows is significantly impacting the time to load the view. One caveat here is that there are some things that can really slow down a table view. For example, if you're using variable-height cells in a table with a lot of rows, that can really slow down table creation. Try not to do that.
#benzado gives some good pointers for improving performance. Trying to work against Cocoa-Touch is always a recipe for pain, so try instead to figure out why your view is taking so long to load. Where is your app spending all that time? What can you do to reduce that load?
I have a button which when pressed makes calls that load information from a series of URLs (about 5 seconds loading time). Right before actually making those calls I want to add a "loading" alert. When I use a UIAlertView the screen dims like it's about to pop up, but it doesn't until the data is loaded - too late! I have no idea what's going on, it's like the calls I'm making to load the data are immediately taking preference over showing the new view, even though they're made right after the calls adding the new view (or showing the alert).
This is a summarized version of the code:
-(void) refresh{
UIAlertView *av = ...
[av show]; //this should pop up before dat begins to load
[myDataSource loadData]; //this contains a series of [NSData initWithURL] calls
[self.tableView reloadData];
//here I would hide the AlertView, but if I do I see it for just s split second
//when the tableView has already reloaded
}
Thanks in advance for any insight!
***EDIT
To anyone who uses performSelectorInBackground beware of the added complexities of creating what is effectively a threaded program. For example, leaks might appear as the new thread doesn't have an autorelease pool - you have to add one, etc.
when you try to retrieve data from the internet (I guess you are using something like [NSString stringWithContentsOfURL: ...]) the main thread is waiting for those data and for this reason the application cannot redraw the interface.
You can try to use:
[mySourceData performSelectorInBackground:#selector(loadData) withObject:nil];
Be careful if you are using coredata to lock the NSManagedObjectContext before doing any operation on it and unlock it when you finish.
If you have a bunch of operations to perform, in addition to performSelectorInBackground: like cescofry wrote, you can use NSOperation and NSOperationQueue.
You probably don't want an UIAlertView for this anyway. Take a look at MBProgressHUD on GitHub.
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