I am learning to develop iPhone applications using iOS 5.
I am trying to create a contact list of sorts (to learn about Core Data).
I have a UITableView embedded in a UINavigationController (I have done this through Editor -> Embed In -> Navigation Controller).
At the end of my saveContact action I have the line:
[self.navigationController popViewControllerAnimated:YES];
To move from the contact creation form to the UITableView which lists all the contacts. The code that fetches the contacts is in viewWillAppear.
Problem is that when I pop the contact creation form the new contact does not show on the list.
I have found in Apple's documentation that I should add the UINavigationControllerDelegate to my UITableViewController, but no success.
Any suggestions?
You need to implement the navigationController:willShowViewController:animated: method of the UINavigationController protocol in your UITableViewController and set the delegate of the navigation controller the table view controller. In you implementation of the method, check if the view that will be shown is equal to your view, and if it is then fetch the results.
If you really want to integrate Core Data with a table view, I would recommend looking into NSFetchedResultsController. It simplifies handling updates to the backing data store, so if you later added background syncing functionality, the background thread could continuously update the store, and the NSFetchedResultsController could then handle updating the table for you. It would also make your current example easier, as all you'd have to do is send save: to Core Data and then the results controller would start updating your table, without using a viewWillAppear: method
Related
I've set up a really simple project using storyboards including two views as shown here: http://i.stack.imgur.com/iRx21.png. The navigation can be done by either selecting a cell in the custom table view or hitting the back button labelled with "<<". Everything works fine except the following:
when I switch between the views, every time an instantiation happens. The profiling shows an increasing number of view objects. I would like to keep only one of each view and instantiation should be happen only once. What am I doing wrong? (I'm using ARC.)
Thanks in advance!
You should not link your back button to the parent view controller. This is what causes the new instantiation.
The way to go is to embed the table view into UINavigationController (in IB, choose Editor -> Imbed In -> Navigation Controller. Then change your segue to a Push segue. You can of course hide the navigation bar etc. to make things look exactly as you like. Then, link the back button to the controller with an IBAction and in the handler do a simple
[self.navigationController popViewControllerAnimated:YES];
This would be the appropriate logic of what you are doing. Of course, you can also push the web view modally and then handle the button click with
[self dismissModalViewControllerAnimated:YES];
I'm currently working on my Favorites implementation. In the end, it should work the same as the favorites features in the Phone book on the iPhone.
I've the following set-up (besides other controllers and classes):
TabBarController (named mainTabBarController)
NavigationController with a Tableview (let's call it listNavController)
ViewController with some components for displaying row details (named detailViewController)
NavigationController with a TableView for favorite records (named favoritesNavController)
From the favoritesNavController, I want to select a row (from listNavController) so I can add a new entry to my Favorites tableview.
So, I decided to re-use my listNavController because it has all the functionality I need. Like searching, index, etc.
I've managed to show the listNavController from the mainTabBarController. So no problem here. When I select a row from the listNavController, it displays my detailViewController for that row. Of course, this was expected because that's in didSelectRowAtIndexPath in listNavController.
But, when I launch a listNavController from my favoritesNavController with the help of presentModelViewController, it still shows the detailViewController when selecting a row.
In this case, I want to return the selected row to my favoritesNavController. Then I can add it to my Favorite's list.
So, how do I differentiate this behaviour in code ? Should I use protocols, delegation, etc. ?
Any tips ?
With regards,
Rutger
It turned out that I was looking in the wrong direction.
The solution to the posted question is as follows:
I created a subclass of my listNavController and overrided the didSelectRowAtIndexPath method. Next I presented this new view controller with a navigation controller as a modal view (presentModalViewController).
Finally I set the delegate and a protocol for the subclassed view controller to the initiating class. This way I can present and dismiss the subclassed view controller from the same controller. A much more clean and MVC way to go!
I'm trying to put an iAd banner in an app that is based on a UINavigationController (it's not the standard nav-base app proposed by xcode, cause I don't need the table view).
I'd like to place an ADBanner on its bottom, to be always visible, no matter how the user pops and pushes views.
I studied the iAdSuite example in the apple sample code, but, though it's reported among the "best practices", I don't think it's the best practice for what I need. It basically declares an ADBannerView in the app delegate class and then implements the ADBannerViewDelegate methods for every single view the app needs. That means implementing the ADBannerViewDelegate methods over and over again on every view controller class you need! It doesn't seem too smart... :(
I'd rather prefer to have an approach more similar to what Apple itself does in the tab bar based app, where you have a part of the window always occupied by the tab controller and all the views switching above without affecting the tab bar view below.
You can't directly put an ADBannerView along with the nav controller in the app delegate, because ADBanner needs to be placed in a view controller (you get a runtime error otherwise).
I tried to subclass from UIViewController, implementing the ADBannerViewDelegate in this class, and place it in the rootViewController along with a UINavigationController but I'm not having good luck with this approach...
Has anybody found a good, simple way to to this? Any hint?
Thank you for any help...
You can have just one class for ADBannerViewDelegate, and just one instance of ADBanner itself. When the currently active view changes, remove ADBanner from the old view, add it as a subview to the new view.
EDIT:
to clarify, you don't need each view implement the ADBannerViewDelegate. You only should have one class implement it (that class doesn't have to be a view controller for that matter).
You would also need to maintain a somewhere a property that would point to the currently active view (e.g. you can update that property in your Navigation Controller's navigationController:didShowViewController:animated:, or come up with your own protocol for that if your views appear in a more complex way).
Then in your ADBannerViewDelegate you'd just resize the view currently pointed to by that current view property. The actual view doesn't even have to know it has an ad in it ;)
I have a very simple iPhone view based application I need help on. It's a view based application with a nav. bar in the footer that switches between 4 view controllers.
What I need to do is pass a UILabel value from view 2 to view 4. The UILabel field is a value calculated in view 2, but I want it to appear in view 4 (if 5+5=10, I want the 10 to appear in view controller 4, not view controller 2).
How do I go about doing this? Does anyone have any sample code I can review? I've searched awhile in Apple's docs and online and haven't found anything helpful yet. Keep in mind I'm a real newb. when it comes to development. I'm just starting to learn!
Thanks in advance.
There are a few ways. I would probably just have a variable created in the application delegate's interface and just change it and access it there.
NSObject *myVariableFromDelegate = [[[UIApplication sharedApplication] delegate] myVariable];
[[[UIApplication sharedApplication] delegate] setMyVariable:10];
Take a look at NSNotificationCenter. You can send a messages and handle them anywhere in the app, best solution in most similar cases.
The application delegate might work for you, but if you are going to have a lot of values to keep track of, you are probably better off implementing a separate class for your data. Otherwise it will get unwieldy quick.
When you load a new view, you pass off a pointer to the data cass to that view controller so that the current values can be pulled out and put into the correct fields. In addition, you could use register for notifications in the view controller to catch any changes that other views make. Just make sure you de-register the notification when the view unloads, and you should be good.
I'm using a UITableViewController for a menu in a game. The table view opens a a view controller for my custom UIView that shows the game. When the game finishes the UIView is notified (which is kinda ruining the MVC principals) and from there I am kinda lost.
Questions:
Can a UIView communicate with its controller? How?
Can one controller talk to the one that started it? How?
How do I transition between all of this complicated web of views and controllers gracefully?
Use a delegate protocol here. Your custom game UIView can use a delegate property and call methods on this delegate when events happen (game over, game paused, view closed, etc). Here's a great post on using delegates: How do I create delegates in Objective-C?
I'd recommend using a UINavigationController. You don't necessarily need to show the navigation bar, but if you nest your view controllers in a navigation controller you have access to -pushViewControllerAnimated: and -popViewControllerAnimated: which make it really easy to navigation between levels of nested view controllers.
Another benefit of UINavigationController - you'll get a nice slide animation when you switch between views.
There are other 3rd party mechanisms out there that you may prefer over the UIKit UINavigationController/UIViewController mechanisms. Check out the Three20 project, in particular the TTNavigationCenter class.