How to speed up slow loading of segue to table view in iphone app - iphone

I have a welcome screen which leads to a table view.
When users tap on a row they are taken via a push segue to a detail view. This loads quickly.
There is also another push segue possible to another table view but this is slow loading.
I think this is because it contains a search bar and data which have to be loaded.
Is there any way I can instantiate this table view when the program loads rather than wait for the segue? The class for the slow loading table view is called BSGlossaryController.
I was thinking something along the lines of myGlossaryController = [[BSGlossaryController alloc]init] but am not sure.

If you want the BSGlossaryController to instantiate at startup, you should delete the segue to it, instantiate it at startup, and push to it manually. You don't want to use alloc init to instantiate it though, that will create a different one than the one in your storyboard. You want to use the UIStoryboard method instantiateViewControllerWithIdentifier: to instantiate it (and make sure you give it an identifier in IB). When it comes time to push to it, you'll want to hook your button (or whatever you're using to trigger the push) to a method that uses pushViewController:animated: to do the push.
If you do this at startup (in the app delegate), then you'll have to assign the newly created BSGlossaryController to a property, and access that in which ever controller you're going to push from. If you can wait to instantiate it until that controller (the one you're pushing from) is on screen, then you can create it in that controller's viewDidLoad method.

Typically, you don't want to load one giant chunk of data at a time. If the chunk is large enough to significantly slow down your view loading, it's a good bet that you need to rethink your approach. Memory issues aside, loading large amounts of data at one time will block the UI of your app as it's loading. This will leave the app unresponsive and the user will wonder what is going on.
You can handle loading large data sets in a few different ways -- presented in order of preference:
Use an NSFetchedResultsController to load your data. This will automatically take care of caching and chunking the data so responsiveness and performance are maintained.
Break your data into smaller subsets. The screen can only display so much data at a time, so it's pointless to load data into memory that isn't currently being presented. Bring in new data as the view requires it.
First present the view (without data), display an activity indicator with a message informing the user that the data load is happening, then bring in the data asynchronously on a background thread. This approach will at least not leave the user wondering what is going on.
Once you post some code and I have a better idea about what you are trying to do and why, I can give more specific answers.

Related

(Multithreading?) Combined with Pushing View Controller

I am creating a game for iphone that has a few hundred levels. These are all loaded into a scroll view when the user presses the start button so that they can choose a level. However, I need to do a lot of calculations, load each level's data from a keyed encoder, and draw a UIImageView on the scrollview before I can show the screen to the user. As it is right now, this is all done by methods I call from viewDidLoad, so it all happens BEFORE the view controller gets pushed onto the stack. As a result, there is a noticeable delay when the user pushes this button.
I would like to have the view controller be pushes immediately, and then have the levels lay themselves out AFTER the view controller is presented, hopefully providing a better user experience. I imagine this would be possible by calling the methods from ViewDidAppear but I would rather start doing the calculations immediately in order to make things as fast as possible.
Is there a way to do this? Possibly using grand central dispatch or assigning the work to another thread?
Thanks for any help!
If you want the UI content to load first (but not necessarily display) before starting your complex calculations, keep your code in the -viewDidLoad method, but insert it after the [super viewDidLoad] call. If the calculations do not involve objects that must be manipulated only on the main thread (i.e. the UI), use Grand Central Dispatch to set up an asynchronous queue for the calculations to be performed in using dispatch_async().
EDIT: I now understand you're using a UINavigationController to push this view onto the stack and that the calculations all have a direct impact on the UI, meaning that they must take place on the main thread. I would thus recommend placing the code in the -viewWillAppear: method. This way, the system should push the view before the calculations are invoked.
Optionally, in the viewDidLoad: method, you could call another method that performs only the calculations and stores the results in variables on an asynchronous thread. The app could then read these calculations in viewDidLoad:.
There is no magic method to use in the delegate. You are asking a super general question: How to do threading in iOS.

Good design for having an ActivityIndicator across entire app

I have the need for an activity indicator view in my app when different views are loading and when data is being retrieved. The problem is the mainVC (where I would place the indicator) is not always aware of when processing is happening so it can start the indicator but it cannot stop it.
e.g. the mainVC loads and then programatically adds a new VC - this VC in turn asks a model to retrieve - it displays data etc. So this newly added VC actually knows when processing is finished and it does not have access to the indicator view (although the indicator is visible at the top).
I was thinking of using notifications - is this the best way of handling this situation?
I'd recommend looking at the brilliant MBProgressHUD library:
https://github.com/matej/MBProgressHUD
It's a very simple set of classes you can use to display loading and progress views that can be accessed by all view controllers in your app. Basically, you can set it up in your app delegate and add it to your app window.
Every view controller can then access the progress view from the delegate and show/hide it when required. It comes with an example project and code - it's very easy to use and customise.
Notifications are one half of the solution. You have to combine them with a persistent object so that you can also get the current state at all times. E.g., when a view controller is about to appear, it needs to read the initial "downloading" state from somewhere, because the VC might have been created after the "start" or "end" notification was sent.
Then, while the VC is alive, it can simply respond to notifications to update the indicator.
This design is particulary important for views, which run the risk of getting unloaded/reloaded all the time.

iOs: When should I initialize upcoming controllers (UIImagePickerController) from a view?

Suppose I have a navigation controller where the next action is to take a picture or select an image from the library.
If I initialize UIImagePickerController during didSelectRowAtIndexPath:, (I believe) the response will be a little slower as the controller needs to initialized. Also, if the user cancels and opens again, it would reinstantiate that controller every time.
However, if I create the controller during viewDidLoad: of the navigation controller, it takes up memory while the user is on that view. Side questions: Does this, however, slow down the loading time of the navigation?
Or should it be done in an NSOperation when the view is loaded?
Overall, what would be the best place to load the ImagePicker?
I'd lazy load the controller when it first gets called (in didSelectRowAtIndexPath) so it wouldn't have to be reloaded every time, and not worry about initialization time.
It seems that in your case you will always need an image picker on didSelectRowAtIndexPath. You can load it on the view and customize (camera, cameraroll, etc.) and present on the row selection. Probably it doesn't matter that much. UIImagePickerController presentation is very slow anyway, especially with the camera.
I don't recommend an NSOperation for this task.

How to Handle an Indefinite Amount of TableViews in an iPhone drill-down app

I've Created a UITableViewController subclass. Do I only need one controller? Do I just instantiate multiple instances of that one subclass?
The iPhone App I'm building will start with a Table of a list of people. If the user taps a person, a new table will be pushed in with a list of Companies they've worked for. If the user then taps a company, they'll see a list of Job Positions. And if they tap a position they'll see a list of people holding those positions.
This could go on forever, and the user could always back up the list.
The App Delegate instantiates the Navigation Controller and the Table View Controller and then pushes it onto the Navigation Controller. But when a user taps a row, now the TVC is creating another TVC.
Is that right or should the
AppDelegate be instantiating all
TVC's? Or does it work out since
they all get pushed onto the Nav
Controller anyway?
Does each Table View instance
need to have a different name or can
they all be called 'mainTVC' or
something like that?
tableViewController *mainTVC = [[tableViewController alloc] init];
Won't I run out of memory? Do i
need to start dropping Table Views
when they're 2 or 3 levels away from
current, and then re-create it if
the user backs up to it?
No need to create multiple TableView's, what I've done in the past is simply re-bind to a different datasource. So keep one TableView and have a datasource for people, then companies, etc...
I'd create a view controller for each type. Presumably you'll want to have special display characteristics like a custom tableview cell to display job positions slightly differently then you would people names.
Other then that, #Ben Gottlieb's answer should work quite well. Use lots of view controllers and handle the didReceiveMemoryWarning: method.
One more thing, if the user drills down so far that you want to say they'll never go all the way back (sort of like having an undo stack) you can use the setViewControllers:animated: UINavigationController method to reset the stack to a certain size (say 15 to implement an 'undo buffer' of 15). With this method you can make sure that the first view controller is always your root view controller and the rest are all drilldown instances.
Option number (2) looks good. You can push quite a lot of view controllers onto the stack before memory becomes an issue. The system will clean up most of the heavyweight memory hogs (ie, the views) in the didReceiveMemoryWarning: method. If you're creating a lot of in-memory structures, you may want to clean them up in that method (be sure to call the inherited method).
To answer your third question, as long as you don't have huge data stores in memory, memory shouldn't be an issue. You SHOULD NOT under any circumstances "drop" tableviews - this would lead to crashes(and there's no way to do non-FILO additions/removals to the navigation stack anyway). Under memory pressure, you should only free "nonessential" items like caches. However, this shouldn't be an issue.
Also, if you have more than 3 or so levels, chances are you need to rethink your UI. If users are drilling down 10 levels, it will be tedious to navigate the stack back.

Passing data from modal navigation controller to parent controller?

I'm starting out in iPhone development, and I'm trying to do a Contacts-style controller to add items to a table. I've got the two controllers designed, but I can't seem to figure out how to pass data between them. How can I get data from the modal controller to its parent?
Just trying to call methods on parentViewController won't work (and results in compiler warnings and crashes). I've considered moving the data out of the controller itself (which is going to happen anyway, I'm just trying to keep things as simple as possible for now), but even then I still have to somehow tell the parent view to refresh its data. Again, how can I do this?
I've considered moving the data out of the controller itself (which is going to happen anyway
I think now may be the time to follow that consideration and create a separate "ContactList" model object to store your data.
Your modal view controller just adds new "Contacts" into the "ContactList".
Your TableViewController should observe the same "ContactList". As items are added/removed to/from the "ContactList" your TableViewController will simply add and remove rows from its tableView.
In this way you will keep each ViewController independent, your code will be more flexible and adding/removing single rows will be much more efficient than reloading an entire tableView.
You either keep a link to the sub view you create and ask it for data that has changed on return, or else ad yourself as a delegate of a subview and have it call you back directly (which does work if you have a valid reference).
I had the same question and found this sample code: http://developer.apple.com/iphone/library/samplecode/LocateMe/Introduction/Intro.html
Helped me a ton and was pretty easy to figure out from the code.
In short, use delegate.
I would suggest you have a look at Lecture 11: Text input, Presenting content modally (May 6) - iPhone App Programming course offered by Stanford. Search for it on iTunes U.
Download this sample app if you want to know how to implement delegate: http://www.stanford.edu/class/cs193p/downloads/11-Pickers.zip