I have a uitableview with a tabbar and a navigation bar. Just below the navigation bar, I want another fixed bar, sticking to the navigation bar even while scrolling through the table, which will display today's date. I know that the displaying the date involves NSDateFrmatter and such, so converting NSDates is not the issue. The issue is bar itself. How can I add such a fixed bar, and add a title (which will be the dates) to it?
There's a couple of ways you could achieve this, but here's what I'd do: first, create a UIViewController subclass, and add a UIToolbar instance to the controller's view with a frame of CGRectMake(0.f, 0.f, 320.f, 44.f). Then, create a UITableView instance, and also add it to the view with a frame of CGRectMake(0.f, 44.f, 320.f, self.view.frame.size.height - 44.f).
Instead of using UITableViewController you will have to subclass UIViewController and put a UIView with you date at the top and then the tableview below it. And set it up as the delegate and data source for the table in the header file and the outlets in Interface Builder.
#interface YourViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, retain) IBOutlet UITableView *tableView;
The only other thing that UITableViewController provides for you that you may need to implement yourself is it will automatically clear the table’s current selection when it receives a viewWillAppear: message.
Related
the main tableview will have rows that is added/created from the user and that row will open their own tableview which also have their own add/create own row. My main question is how to make sure each row thats added in the main tableview opens their own tableview (as blank until added from user).
This link i've seen is the closest How can I move to another view controller when the user clicks on a row? but not exactly what Im looking for. Most of the samples/tutor is all ususally populated or already have an array in their tableview. I wanted to make mines both completely nothing in it but added only by the users and main tableview each row opens its own tableview.
I already have two tableview one is main and other is sub to each row. I was able to insert row in main table view but it opens the same tableview as the other rows in the main tableview and would like to know how to make sure each row in main tableview opens their own blank tableview.
Usually your view controller controls the tableView. I guess you are trying to fit in there multiple table views and logic for each one. Instead, just create controllers for each table.
First create your main view controller using a UIViewController template (don't use a TableViewController). Use a XIB and add there a TableView element, OR create a UITableView instance using code.
Now create a class conforming to the delegate and datasource, protocols. This doesn't need to be a view controller. Example:
// MiniTVC.h
#interface MiniTVC : NSObject <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, retain) IBOutlet UITableView *tableView;
#property (nonatomic, retain) NSArray *array;
-(id) initWithTableView:(UITableView*)tableView array:(NSArray*)array;
#end
and implement the delegate and datasource methods as usual. You need at least the following:
tableView:heightForRowAtIndexPath:
numberOfSectionsInTableView:
tableView:numberOfRowsInSection:
tableView:cellForRowAtIndexPath:
Then back to your main view controller, you create (or hook from the interface designer using IBOutlets) a tableView and set its delegate and datasource to your MiniTVC class, eg:
// sample table created by code
CGRect frame = CGRectMake(50,50,100,100);
UITableView *tableView = [[UITableView alloc] initWithFrame:frame]
[self.view addSubView:tableView];
// set the datasource/delegate
MiniTVC *miniTVC = [[MiniTVC alloc] initWithTableView:self.tableView array:someArray];
tableView.dataSource = self.miniTVC;
tableView.delegate = self.miniTVC;
You can repeat this process creating another UITableView + MiniTVC from inside a custom UITableViewCell. Or you could make the UITableViewCell conform to the table delegate/datasource and implement there the methods.
Btw, creating tableviews inside tableviews is a bit unusual. Since they are both UIViewScroll subclasses, it could lead to unexpected behaviour, tho I haven't tried myself.
I'm using a UITableViewController and want to add a searchbar.
My options are [self.tableview addSubview:searchBar] or self.tableview.tableHeaderView = searchBar
Both options will scroll the searchbar along the rest of the tableview, which I understand. But is there a way to lock elements up, instead of using a UIViewController or changing the frame origin on scroll?
I'm thinking of a way to get above the current view hierarchy and add a subview onto that.
I tried the opposite approach, to add a view to the superview and bring that to front
[[self.tableView superview] addSubview:searchBar];
[[self.tableView superview] bringSubviewToFront:searchBar];
}
but it didn't work.
UITableViewControllers are UIViewControllers that have their main view property being an UITableView. Thus this UITableView do takes all the screen.
The approach you are looking for is to use a standard UIViewController whose view is a standard UIView, and add your UISearchBar and the UITableView as a subview to it in IB.
To do this, simply:
Change the class of your view controller and instead mention that it conforms to the tableview-associated protocols : change #interface UITableViewController to #interface UIViewController <UITableViewDelegate, UITableViewDataSource>
Add a #property(nonatomic, retain) IBOutlet UITableView* tableView property to your header file, and the associated #synthesize tableView; statement in the implementation. Don't forget to set this property back to nil (self.tableView = nil) in your dealloc for good memory managment
Link your UITableView instance in InterfaceBuilder to this newly created IBOutlet.
Thus you still have a UITableView but this won't be the main view that takes all your screen; instead you can layout your tableView like you want and make it take only a part of your screen, and position the UISearchBar above it.
Another approach would be to use the UISearchDisplayController to manage your UISearchBar.
I have a UIViewController. I want to add a UIToolbar to the bottom, but IB is not letting me. How can I achieve this?
Note:
The UIViewController is part of a UINavigationController. I'm not sure if this affects the visibility of the toolbar.
Starting from iOS 3.0 you can set toolbar items you want using following UIViewController's method:
- (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated
of simply set or override toolbarItems property.
And toolbar will appear automatically if you put your view controller inside navigation controller.
You can't add toolbar in IB, in IB all you can do is - set a dummy toolbar / navigation bar / tabBar etc. so that you can simulate them to arrange your view's subviews appropriately.
To set the toolbar for that viewController, you have to fill the UIViewController's:
setToolbarItems:animated:
or
#property(nonatomic, retain) NSArray *toolbarItems
so this toolbar and its items will be displayed when your viewController is presented.
I'm working on an app that has three table view controllers in a navigation stack. The root view controller and the second VC have toolbars, but I want to add a subview to the second view controller like this. (The color is just there for visualization.)
I want to add the view programmatically, since I haven't been able to do it with IB without major headaches. Right now, I've been able to kind of get what I want by drawing a UIView in the second view controller like this:
- (void)viewDidLoad {
[super viewDidLoad]
UIView *detailView = [[UIView alloc] initWithFrame:CGRectMake(0, 392, 320, 44)];
detailView = [UIColor redColor];
[self.navigationController.view addSubview:detailView];
[detailView release];
}
The problem with this approach is that once the UIView is loaded in the second view controller, it stays loaded and is drawn in the third and root view controllers. I've tried a variety of methods of removing the UIView, including setting the detailView to nil in viewDidUnload, calling removeFromSuperview in didSelectRowAtIndexPath (which removed the view from the whole stack).
I've also tried adding the subview to self.view, but that pushes it below the visible area of the table view, so I have to scroll up to see it, and it snaps back down when I let go.
Clearly, adding this subview to the navigation controller is not the best way to do what I want, but I'm at a loss as to where to go from here.
As you've already discovered, you definitely should not be reaching up into the navigation controller's view.
You want your SecondViewController to be an UIViewController that implements the UITableViewDelegate and UITableViewDataSource and whose view lays out the UITableView and the UIView you wish to use for your stationary 'footer' in it's own main UIView.
It helps to keep in mind that UITableViewController is ultimately is just a convenience for creating a view controller whose view consists entirely of a UITableView.
Anyway, rather than attempt to put a pile of that code inline in this answer, you can browse it (or svn co) from this read-only svn repo.
EDITED (now that it's not midnight, putting some code/explanation directly in answer):
For the controller to be pushed onto the nav stack that needs the footer create a new UIViewController-based class (do NOT check the 'UITableViewController subclass' box in the template selection dialog).
Add instance variables for the UITableView and the UIView that is to be the extra bottom view.
#interface SecondViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
UITableView* tableView;
UIView* customFooterView;
}
#property (nonatomic,retain) IBOutlet UITableView* tableView;
#property (nonatomic,retain) IBOutlet UIView* customFooterView;
#end
In IB add a UITableView and UIView to the existing root view for the controller and lay them out as desired (probably worth altering the auto-resize parameters too if your app can be used in both landscape and portrait). Hook up the two views to the outlets defined for them in the "File's Owner" and also ensure you hook up the UITableView's delegate and dataSource properties to point at the "File's Owner."
Then just implement the UITableViewDelegate and UITableViewDataSource protocols as appropriate for your application.
If you want to lay out the entire 'footer' view in IB then go right ahead. Otherwise you can easily add items programmatically in viewDidLoad (and remember to tear it down in viewDidUnload).
I don't like the approach. You should put your table view inside another view, and put your detail view together in that view.
Despite of that, I think you can remove your view in viewWillDisappear method of your view controller. I also notice that you did not keep your detailView as a private variable, which you should do because you need to reference it when removing it later (I still wonder how you have done it.)
Note that viewDidUnload is called in case of view unloading (i.e. releasing from its controller), so it is not related to navigation.
Not sure which behavior you're looking for but try one of these:
Assign the detailView to the tableFooterView property of the tableview on the second VC.
Reduce the height of the table view and add the detailView to self.view.
quick question - I have my "first view" which is going to be the ONLY view in my application. I've added a UITabBar to this view using Interface Builder. I am simply wanting to use this as a menu to control the contents of a scroll view.
For example, the user clicks on the first icon in the UITabBar - I get its tag, then based on that, will add a subview to the scrollview. This is working ok....
...but, I have been viewing a few tutorials on tabbars and it seems that 99% of the time they are used to control views. I simply want it to return my tags.
So my question is this: is what I am doing ok?? Can it be used for simply returning a value rather than changing a view? If this is common/OK practice, how on earth do I reference it?
I can get the selected item tag, but cannot actually reference the uiTabBar to make the first button selected. In my .h file, I tried to specify an IBOutlet for the controller, but I cannot link this in IB.
thanks for any info!
To receive notifications that a tab bar item has been clicked you need to modify your view controller to implement the UITabBarDelegate protocol and add an outlet for the tab bar. To do this, modify your declaration in MyViewController.h to something like this:
#interface MyViewController : UIViewController <UITabBarDelegate> {
UITabBar *tabBar;
...
}
#property (nonatomic, assign) IBOutlet UITabBar *tabBar;
Then implement the tabBar:didSelectItem method in MyViewController.m as follows:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
NSLog(#"Tab clicked: %d", item.tag);
}
You must also set your view controller as the delegate of the tab bar in IB. (hint: connect up the 'delegate' outlet from the tab bar to File's Owner).
To access the tab bar from your view controller use the tabBar property and do things like:
self.tabBar.selectedItem = [self.tabBar.items objectAtIndex:0];
As to whether this is a good idea - why not? All the tutorials show a tab bar being used with a UITabBarContoller to switch views, but it is designed to operate as a stand-alone control as well. As long as you are not breaking any HIG rules then how you implement your interface switching is up to you.