Since I am a newbie in iPhone development, I need some advice on how to structure my xib file in order to get the following (essentially, it should be very similar to Google Places app).
I need a NavigationController with:
Map with search functionality.
TableView with search functionality (ideally, the search should be shared between map and TableView).
One view to show details of a selected item, whatever the source view is (map or table).
Map view should have a button to show listing view, and viceversa.
My doubt is, what do I have to nest where? I have a NavigationController with its View Controller set to another class with its own xib, but I don't know how to go on.
Should I create a View with a search bar and another SubView to switch between Map and Table? Or is it better to have two full views each one with its own search bar?
EDIT 1
Finally I have decided to implement the following structure:
- TabBarController
- LugaresNavController (UINavigationController)
- LugaresViewController (UIViewController)
- UISearch
- SubView (UIView)
- MapViewController (UIViewController)
- TableViewController (UITableViewController)
MapViewController and TableViewController have their own xib files. What I want is to have the ability to switch between them into SubView, but I am not able to do it.
I have assigned MapViewController and TableViewController file's owner to their respective class in the xib files, and also have specified which xib to load at the attributes of their representation in the xib corresponding to LugaresViewController, which is their parent.
When I run the application, all I can see is the TabBar with the NavBar and the UISearch. The frame where SubView should render either the map or the table is showing blank...
What am I doing wrong here?
Your fundamental problem is that you are getting your different parent-child hierarchies confused.
To recap: MVC is Model, View and Controller.
iOS has TWO different parent-child hierarchies: One for the controllers and one for the views.
The following are part of the controller parent-child hierarchy:
- TabBarController
- LugaresNavController (UINavigationController)
- LugaresViewController (UIViewController)
This means that LugaresViewController.parentViewController should be LugaresNavController and so on.
However the following doesn't make any sense:
- SubView (UIView)
- MapViewController (UIViewController)
- TableViewController (UITableViewController)
Views can have subviews but views can't have subviewcontrollers,
Are you doing the following?
- SubView (UIView)
- MapViewController.view (UIViewController s view is a subview of Subview)
- TableViewController.view (UITableViewController s view is a subview of Subview)
This is a view parent-child hierarchy. This means that:
SubView has two subviews (MapViewController.view and TableViewController.view)
MapViewController.parentViewController is nil.
MapViewController.navigationController is nil.
you can use view transtions to switch between MapViewController.view & TableViewController.view but not viewController transitions (such as presentModal... or push or pop ViewController...).
If this is what you want, then you just have to make sure that you do:
[SubView addSubview: MapViewController.view];
[SubView addSubview: TableViewController.view];
Incidentally, SubView is a terrible name. Usually we call those containerView or something like that.
subview is such an important concept you want to be able to diffrentiate the concept of a subview from the instance of that view. It's like naming your child "Kid" or your dog "Puppy".
your App is similar to mine, what I've done:
- TabBarController
- TableView
- SearchBar
- DetailButton ----\
- MapView \____ push ModalViewController
- SearchBar /
- DetailButton ----/
now if someone pushes a button in the table view or map view I'm opening the same View but pass other information to initialize it. btw. what is a LugaresViewController?
First try only adding a TableView and a MapView in each tab and look if the nib-binding works well. If not, you're missing something, load nib named or class type. Afterwards you can add the SearchBarController's and provide functionality for that.
First of all, I can't really say I agree with your tabbar application. I think a navigation application might work better for this idea. The first view would then have the navigationbar automatically added, with below the UISearchbar, a window, and a normal tabbar.
The UIWindow should contain a subview. That would be either the table, or the map. When you first load the application, and show, say, the table, you'd do:
[window addSubview:tableViewController];
When you switch to the mapview, you'd do something like:
[tableViewController removeFromSuperview];
[window addSubview:mapViewController];
So, for switching views, that's where the UITabBar comes into play. Make sure the tabbar has two segments. Hook up an IBAction to that, which looks a bit like:
-(IBAction)segmentedControlIndexChanged {
switch (segmentedControl.selectedSegmentIndex} {
case 0:
<call function for removing mapview and adding tableview>
case 1:
<call function for removing tableview and adding mapview>
default:
break;
}
}
Last but definately not least, which might be the answer to your edit: make sure you've connected all the connectors in Interface Builder (or, if your using XCode 4, just the .xib-file), from the .xib to the File Owner's.
EDIT: Ofcourse, the detail-view for the items pressed on the table/map is pushed in the navigationItem, so the back-button is automatically created and functional in your detailview.
Good luck!
Related
I have a UITableViewController embedded on a UINavigationController. This tableView is an instance of NSFetchedResultsController.
I need to add a Toolbar between the NavigationController's top bar and the TableViewController, but I can't figure out how to do it (I don't even know if it's possible).
I want to do something like Apple did with their WWDC App (except that they don't have the TableViewController embedded in the NavigationController).
I need to have some controls on the bar to drive the NSFetchedResultsController.
Some people suggested to people with similar problems to use a UITableView instead of a TVC, but I do need to have a TVC as an instance of NSFetchedResultsController.
Any ideas on how to accomplish this?
Would I have to do it programmatically? If so, how?
Btw, I'm targeting iOS6+ with storyboards and ARC.
The approach I prefer is to use a UIViewController at the outer level, containing your toolbar and a container view that holds the table. Then build your table in a separate UITableViewController and wire it into the container view using an embed segue. Overall, I think this makes the code more modular and easier to follow because the high-level structure is laid out in the storyboard.
The steps to use an embed segue are as follows:
Control-drag from the container view to the view controller you want to embed and select the "Embed" option.
Give the embed segue an identifier in the attributes inspector.
Configure the table view controller in the parent's prepareForSegue method, checking for your segue's identifier.
There is an example of this in my VCollectionViewGridLayout library. Take a look at the Sort & Filter example project.
Technical Note TN2154: UIScrollView And Autolayout provides another solution:
Note that you can make a subview of the scroll view appear to float (not scroll) over the other scrolling content by creating constraints between the view and a view outside the scroll view’s subtree, such as the scroll view’s superview.
That is, even if a scroll view (such as a table view) modifies the subview's frame, the auto layout engine will reset it on the next layout pass.
you need use UIViewController, then add tool bar and tableView instance of NSFetchedResultsController class inside it in storyboard
You can make a topBar of any UIView and then pass it as the tableHeaderView.
It may help you.
Use UIViewController instead of just UITableViewController where you can easily place other controls apart from just a UITableView.
Hope this helps.
You can use the UITableViewController (keep the niceties such as UIRefreshControl support and keyboard avoidance). You just have to embed your toolbar in a plain view and place that in your tableHeaderView. Then implement this scroll view delegate method to lock.
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect rect = self.toolbarContainerView.frame;
rect.origin.y = MIN(0,scrollView.contentOffset.y + scrollView.contentInset.top);
self.toolbarContainerView.frame = rect;
}
Note that if you also use section header you will have to send those views behind your tableHeaderView otherwise they will float over the tableHeaderView.
I have implemented Facebook type left Slide Bar layout in my first view of iphone app. Now, I want to implement this throughout all view controllers (screens) in application, means irrespective of the view the left slide bar should appear on clicking the menu button at the top in all views.
My app contains 25-30 viewcontrollers and my slide bar layout should appear in all views..
Can anyone suggest, how can I include above FB Layout in all views
Thanks in advance
Ramu
Simple, The one view controller in which you have implemented the FB layout and is working. Make it the base class on top of UIViewController. And as for the rest of all the ViewControllers, inherit them from the MasterClass that you just created. Doing this will make the swipe gesture that brings forth the slide bar available to all of your 30 view controllers.
EDIT
Lets see, we have UIViewController, now first of all you create a UIViewController's subclass: say FBViewController ..In this FBViewController you implement the FBLayout such that the swipe and all is working ..on it ..test your app first using only this FBViewController as rootViewController and check all the functionalities.Once everything is working fine, grow on it. What I mean is this.
Say you are creating a Tabbed application, where all the three tabs are supposed to have the same FBLayout style. Then do these steps.
Create FBViewController, it inherits from UIViewController (using UIViewController subclass template, also check the generate XIB button) also have an XIB for it FBViewController.XIB (fully implement FBLayout in it. This will be your base class)
Then Create three more ViewController classes (FirstViewController, SecondViewController, ThirdViewController) again from the UIViewController subclass template, but for these three dont check the generate XIB button. these three will use the XIB of the base class FBViewController (If you are wondering how, then go to step 3 :))
Go to header file of FirstViewController class you created, there you can see #interface FirstViewController: UIViewController replace it with #interface FirstViewController: FBViewController, but before it import FBViewController.h to the header file. Repeat the same for the Other two classes- SecondViewController, ThirdViewController. Since these three will inherit from FBViewController. In their viewDidLoad [super viewDidLoad] will load FBViewController and generate the view. after [super viewDidLoad]; line you can implement ur own methods.
In the three classes just change the initWithNibName method to change the tab bar name and title.
In appDelegate go to didFinishLaunching method and put these three view controller in a tabBarController, set the tabBarController as rootViewController.
And we are done. If your FBViewController is working fine. You will see that all the three classes behave the same way. Thanx to the power of Inheritance.
Cheers, play a bit, have fun.
I had the same problem. I was using a facebook-style menu, and needed it in all view controllers.
You can use a Container Controller. A Container Controller can have the base layout, which I defined in a nib, containing a navigation bar and a bar button item to toggle the menu, and then add child view controllers and remove them as you need them. That way, you can throw whatever view controller you need to the container controller and it will display it.
You can also add gesture control to slide open/close the menu easily.
You will have to make the Container controller your self, it is not standard. I think it is better solution than inheritance, since if you use inheritance you can't make a for example UITableViewController, all your controllers will be of the type of yuor master class. Of course, you can fix this anyway with delegates.
It may sound a bit tricky, but see this tutorial which I used: http://www.cocoanetics.com/2012/04/containing-viewcontrollers/
It wasn't accutally that hard.
EDIT: You can just use a UINavigationController as well. Just set the base view controller to the view controller you want to display, and you can prevent it adding the back button etc to the nav bar by overriding the default methods. Make a UINavigationController as rootNavigationController. Might be simpler.
I'd highly recommend using an open source solution that handles all the edge cases for you - it's both the easiest, most robust and most maintainable (since the community will keep it up to date fro you). ViewDeck seems to be the most popular solution though I have also had success with PPRevealSideViewController. They both provide a very robust implementation that would take a long time to do yourself (e.g. you can optionally enable swipe on the navigation bar or even content area to open the menu). Furthermore they separate the sliding logic and the revealed menu (which can be any view controller you like, but most likely a table view controller) out of your other view controllers. That way any viewcontroller can have a side menu without duplicating any code - separation of concern is great :)
You can make a SharedInstance for SideView class. I am doing same thing for iAD to show throught-out the application.
Please see the the link of iAdSuite ,In which the BannerViewController is SharedInstance so they are easily used for all View Controller
http://developer.apple.com/library/ios/#samplecode/iAdSuite/Listings/TabbedBanner_TabbedBanner_BannerViewController_m.html
All,
It's not this: Science At Hand - Adventures in UISplitViewController. That really goes from the UITabBarController rather than the cells in the Master.
Let's say I want to create a SplitViewController. On the left side I have different types of cells in the same list (It's not going on Apple Store, so I don't care if it's Apple iOk or not). For each of the different cell types I want to have a different DetailView controller. Cell Type A shows DetailView A, Cell Type B shows DetailView B.
How do I update the SplitViewController subviews to shift detailviews?
Can I just put the navigation controller under the detail and then add viewControllers to that? Using the get based on seque name or get view from storyboard?
Some other, really obvious way that I'm just missing.
For bonus points, I would like a way to detect that I'm leaving one detailview (for saving) and moving to a different detailview (A different cell type button was pressed)
It turns out it was simple.
If you do the obvious (who would have thought?) it works just fine. I created my different cellviews. Each cell view has details link that I just linked to a series of view controllers. I just had to change the seque so that it was a replace and it put the view into the detail view.
I'm make this sample in GitHub
https://github.com/AlfonsoMoreno/MultipleDetailView
MasterViewController is UITableViewController
FirstDetailViewController is UIViewController
SecondDetailViewController is UITableViewController
You can add more views!!!
Please watch MultipleDetailViewManager class!!!
Hi I have placed three button similar to UISegmentcontrol. But its not, its just image buttons. Here I need to have a class called MainView(UIView) and child views like Breakfast, Lunch and Dinners(UITableView for all child view). By default MainView should load the breakfast class if i click the dinner button it should take me to the dinner class. I am able to work with single tableview but I dont know how to load other classes on clicking the button from the parent class.
The child views should appear for the full screen except the navigation items. Can you please provide me you support? Thanks
Switching between multiple different views using a UISegmentedControl, similar to iCal or the AppStore application.
Follow this link: HERE
The solution in this link is hands down the best solution I've found about the issue so far. With a little bit of adjustment it also worked fine with a tabBar at the bottom.
You want to display a new view controller on your navigation controller.
// .h file
- (IBAction)dinnerButtonPressed;
// .m file
- (IBAction)dinnerButtonPressed {
DinnerViewController *controller = [[[DinnerViewController alloc] init] autorelease];
[self.navigationController pushViewController:controller animated:YES];
}
And connect your button to the dinnerButtonPressed action.
The method creates a new DinnerViewController and displays it onto your navigation controller. You can then configure the layout of the dinner view controller in it's own xib (for example, you could add a table view ...)
From your comments to deanWombourne, I understand what you want to do. To accomplish that you have to modify the datasource that your current tableView is linked to, and then reload the tableView with new datasource.
But if I were you, I would go with deanWombourne recommendation and put each of those breakfast, lunch and dinner in separate views and push them into the stack, or I would go with UITabBar and put a tableView in each.
I have a three view tab bar app the second view of which I want to contain a navigation controller. in the navcontroller the first/root view will be a custom uiview containing a uitableview that when you touch a cell will push another custom uiview in to disclose details about the touched cell.
I have found the documentation on doing this but it is not making sense to me or seems to be flying over my head. The docs say that you have to create the uiviewcontroller located in the navcontroller views or at least refer to them programatically. I have been using Interface builder and have become quite comfortable using it, so doing it programatically scares me a bit.
Also, This piece of code from the documentation seems troubling:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:myNavigationController.view];
}
above taken from "ViewController Programming for iPhoneOS" apple documentation
wouldn't this load up and display the UINavigationView immediately?
one problem is I dont want to display the navView immediately. the navController/stack is a secondary tab. So how and where do I impliment my navController(right now I have it instaciated in my delegate(which I think is correct)? I've been able to load up a basic UInavigationController with a navigation bar and a blank view, --minus the custom content view, through interface builder but I'm at a loss as to how to populate the custom content views.
Hope this makes sense.
Any help would be appreciated,
Nick
The first thing to understand is how UINavigationController works. It pushes UIViewControllers, not views. So, when something happens in your second tab (where the UINavigationController lives) you will push a UIViewController onto the stack.
This is typically done in:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
Which is part of the UITableViewDelegate Protocol.
So, when tableView:didSelectRowAtIndexPath is called, you need to figure out which UIViewController to push onto the stack. You can either load this View Controller from a nib, or create it programatically. Since you feel comfortable with IB, I would suggest loading it from a nib.
I would not worry about trivia like "where should I instantiate my UINavigationController?" right now. First, get it working. Then worry about where things "should" go.
It might be best to get the UINavigationController stuff working in a separate project, then fold it into your main project. This lets you ignore lots of little details while you focus on the Navigation Controller.