Tab Bar on TableView? - iphone

Expecting your well advice!
I have a TableView(Grouped Table created via I.B). I'm showing some data on the table when code executes using Navigation Controller view. I want to add a "Tab Bar" in my Table view whether through I.B (or) Programmatically. For ex: Launch built-in "Clock" app, where you can see a Tab Bar which has options of 'World Clock', 'Alarm', 'Stop Watch' and 'Timer' in single view itself.
I tried to create like same by adding a 'Tab Bar' in I.B, but drag and drop of Tab Bar doesn't sit in the Table View. I don't know why. (or) else i even tried programmatically to create it in the Table View, but not succeeded. Is it not possible?
Can anyone please help me on pointing out the code or samples?
thanks.
Calve/

I think you are taking the wrong approach. Adding a tab bar to your table view is wrong. You are supposed to start with the tab bar app and add a navigation controller to that tab bar app. Inside the navigation controller you can add a view with a table on it.

You need to add it to your parent controller's view. Also the tempView element is not necessary.
E.g. if the app uses a navigation controller as the main view controller you would add this to your custom UITableViewController class:
- (void)viewDidLoad
{
[super viewDidLoad]; UITabBar* tabBarView = [[UITabBar alloc] initWithFrame:CGRectMake(0, 430, 320, 50)];
NSArray* tabbarItems = [[NSArray alloc] initWithObjects:[[UITabBarItem alloc] initWithTitle:#"Item1" image:nil tag:1],[[UITabBarItem alloc] initWithTitle:#"Item2" image:nil tag:2],[[UITabBarItem alloc] initWithTitle:#"Item3" image:nil tag:3], nil];
tabBarView.items = tabbarItems;
[self.navigationController.view addSubview:tabBarView];
}

Try creating a UIView and adding a tabBar to that view, and now place this view inside your table. I tried this and its working,
So your function cellForRowAtIndexPath will look like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
UIView *tempView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
UITabBar* tabBarView = [[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
NSArray* tabbarItems = [[NSArray alloc] initWithObjects:[[UITabBarItem alloc] initWithTitle:#"Item1" image:nil tag:1],[[UITabBarItem alloc] initWithTitle:#"Item2" image:nil tag:2],[[UITabBarItem alloc] initWithTitle:#"Item3" image:nil tag:3], nil];
tabBarView.items = tabbarItems;
[tempView addSubview:tabBarView];
[cell addSubview:tempView];
return cell;
}
So now instead of using default cell you can customize it to the way you want.Also I havent considered memory release issue so u might need to update the code to release the allocated memory.

Related

scrollsToTop not working with UIViewController containment

Using SDK 6.1, Xcode 4.6.1, I make a new project Master-Detail iOS App, ARC, no storyboards.
Then in the DetailViewController, in the viewDidLoad I add two UITableViews contained in UIViewControllers and make sure the second one is hidden like this:
- (void)viewDidLoad
{
[super viewDidLoad];
UIViewController *lViewController1 = [[UIViewController alloc] init];
UITableView *lTableView1 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView1.scrollsToTop = YES;
[lViewController1.view addSubview: lTableView1];
lTableView1.dataSource = self;
[self.view addSubview: lViewController1.view];
[self addChildViewController: lViewController1];
UIViewController *lViewController2 = [[UIViewController alloc] init];
UITableView *lTableView2 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView2.scrollsToTop = YES;
[lViewController2.view addSubview: lTableView2];
lTableView2.dataSource = self;
[self.view addSubview: lViewController2.view];
[self addChildViewController: lViewController2];
// now hide the view in view controller 2
lViewController2.view.hidden = YES;
}
(I make sure the DetailViewController is a datasource that returns 100 rows of UITableViewCells with the textLabel.text set to #"hello")
The presence of the second view controller makes that scrollsToTop (tapping on the status bar) does not work anymore. If I do not use UIViewController containment and just add two UITableViews and set the second one to be hidden, scrollsToTop does work.
What am I doing wrong?
scrollsToTop only works on a single visible view. From the documentation:
This gesture works on a single visible scroll view; if there are multiple scroll views (for example, a date picker) with this property set, or if the delegate returns NO in scrollViewShouldScrollToTop:, UIScrollView ignores the request. After the scroll view scrolls to the top of the content view, it sends the delegate a scrollViewDidScrollToTop: message.
You could try calling [tableView setContentOffset:CGPointZero animated:YES] on each of your table (or scroll) views manually instead. To do this, implement the scrollViewShouldScrollToTop: method in the UIScrollViewDelegate protocol:
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
[lTableView1 setContentOffset:CGPointZero animated:YES];
[lTableView2 setContentOffset:CGPointZero animated:YES];
return NO;
}
You can only set 1 ScrollView per ViewController with property .scrollsToTop = YES.
If you set 2 scrollview.scrollsTopTop = YES, it will simply stop functioning.
ie: your sample project (DetailViewController.m) update following lines,
line48: lTableView1.scrollsToTop = YES;
line56: lTableView2.scrollsToTop = NO;
then, scrollsToTop works correctly. If there are more than 1 scrollview you wish to concurrently setScrollsToTop, keep digging around. good luck!
I am currently experimenting with your project. When
lViewController2.view.hidden = YES;
is replaced with
lTableView2.hidden = YES;
then the scrolling works, even with controller containment.
I tried to insert a view between the controller's view and the table and then hide this view, but the table was not scrolling.
I tried to hide the controller by experimenting with shouldAutomaticallyForwardAppearanceMethods but the table was not scrolling.
Result: From my experiments, only one scroll view must be visible in the view hierarchy and the hidden property of the parent views is not checked out. hidden must be set to NO on all other scroll views, not their parent views.
After testing several options and various hits and try I finally settled to one final solution, i.e. setBounds: of scrollView (that is tableView in your case) and it works good. You'll have to put extra effort for animation although.
CGRect frame = scrollView.frame;
frame.origin.x = 0;
frame.origin.y = 0;
[scrollView setBounds:frame];
By the way in your case, try returning YES to
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;
Although if not defined, assumes YES.
I have used this and now it works fine.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIViewController *lViewController1 = [[UIViewController alloc] init];
UITableView *lTableView1 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView1.scrollsToTop = YES;
[lViewController1.view addSubview: lTableView1];
lTableView1.dataSource = self;
[self.view addSubview: lViewController1.view];
[self addChildViewController: lViewController1];
lTableView1.tag=1;
UIViewController *lViewController2 = [[UIViewController alloc] init];
UITableView *lTableView2 = [[UITableView alloc] initWithFrame: self.view.frame];
lTableView2.scrollsToTop = NO;
[lViewController2.view addSubview: lTableView2];
lTableView2.dataSource = self;
[self.view addSubview: lViewController2.view];
[self addChildViewController: lViewController2];
lTableView2.tag=2;
// now hide the view in view controller 2
lViewController2.view.hidden = YES;
}
- (NSUInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSUInteger)section {
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * const kCellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"hello %d %d",indexPath.row, tableView.tag];
return cell;
}

Hide UIPopover after selecting row

I am new to iPad developer,
I am using UIPopover in my application, when i select any row in my popover, my popover is not getting hide it still in the view, it is getting hide when i touch outside anywhere on the screen.
I want to hide popover after user selects any row.
here is my code snippet,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
for(int index=0;index<=indexPath.row;index++)
{
UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];
lbl.text=cell.textLabel.text;
}
}
Logic: When i select any row of popover corresponding text will be fetched and gets stored into label.
Any help will be appreciated.
EDIT
UIViewController* popoverContent = [[UIViewController alloc]init];
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(110, 0, 500, 4)];
popoverPolicyNameTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 250, 200) style:UITableViewStylePlain];// size of tableview inside popover
[popoverPolicyNameTable setDelegate:(id<UITableViewDelegate>)self];
[popoverPolicyNameTable setDataSource:(id<UITableViewDataSource>)self];
[self.view addSubview:popoverPolicyNameTable];
[popoverPolicyNameTable release];
[popoverView addSubview:popoverPolicyNameTable];
popoverContent.view = popoverView;
popoverContent.contentSizeForViewInPopover = CGSizeMake(250, 200); //size of popover border
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
[self.popoverController presentPopoverFromRect:CGRectMake(350,100, 35, 35) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES]; //size of arrow
[popoverContent release];
[popoverView release];
You need to implement something like this
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController1{
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController=nil;
}
Add one variable inside the Class which is having your UITableView:
id parent;
Then properties and synthesize it:
#property(nonatomic, retain) id parent;
#synthesize parent;
Then where you are creating the object of this ViewController to add in Popovercontroller, do like this
myTableViewController.parent = myPopoverControllerObject;
Now in didSelectRowAtIndexPath:
[parent dismissPopoverAnimated:YES];
And you are done!!!
Use delegation and notify your delegate that the user selected an item in the list. The delegate will know how to dismiss the view controller.
This approach is better because it's container agnostic, and you can reuse your view controller outside a popover: for example, using navigation controller on iPhone
Make Popover controller as class member variable.
Then on clicking on table view click method call dismiss method of that popovercontoller.

UIActivityIndicator in tableviewcell Showing Up Late when loading the detailview?

I have a tableview with responding detialview. In the detailview I have some images and labes that is loaded from a URL. I'm trying to add a UIActivityindicatorview to the cell to show that is loading. I have handled that but it shows up to late and does not disappear when I go back to the tableview. I have looked all over to find a simple solution, but failed...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ReaDetailViewController *reaDetail = [[ReaDetailViewController alloc] initWithNibName:#"ReaDetailViewController" bundle:nil];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIActivityIndicatorView *activityView =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[activityView startAnimating];
[cell setAccessoryView:activityView];
[activityView release];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
{
reaDetail.petImageString = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"image"]];
reaDetail.petLabelString = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"description"]];
reaDetail.petLabelString1 = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"description1"]];
reaDetail.petLabelString2 = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"description2"]];
reaDetail.title = [[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"name"];
}
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:reaDetail animated:YES];
[reaDetail release];
}
Any help is very helpful !
I understand that you want to make the activity view to be animated while you load your view controller. The problem is the activity view won't start animating until you return from this selection method... which is about the time when your controller is ready to be pushed.
2 options then:
You could exit from the method asap, calling perfomSelector:onMainThread to do the init steps of the view controller to be pushed
Or even better, push the view controller asap, and do its init process in the viewDidLoad or viewWillAppear methods of this controller (you can add the activity controller in this new view).
If you pick the 1st option, you should call the deselectRowAtIndexPath method after you've pushed the new view controller and call stopAnimating on the indicator view from this deselectRowAtIndexPath method.

Can't edit any objects in method

I have a weird problem. I have a tab bar application. When I wanna set the text of an UILabel in any method, there happens nothing.
For example, nothing happens with 'label1' when I call this method:
-(void)setOne:(NSMutableArray *)theArray {
label1 = [[UILabel alloc] init];
label1.text = #"Test";
}
Does anyone have a solution for this problem?
Thanks,
Jelle
When you call this method a new label is created and the connection to the label which was previously associated with this ivar is lost. This could also be a memory leak.
Edit:
Depending on the rest of your code, this could work:
-(void)setOne:(NSMutableArray *)theArray {
label1.text = #"Test";
}
You don't see anything happened because you create new instance of label and do not add it anywhere. If you really want to add new label to your view then create it with appropriate frame and actually add it to some view, e.g.
-(void)setOne:(NSMutableArray *)theArray {
label1 = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10.0f, 200.0f, 30.0f)];
label1.text = #"Test";
[self.view addSubview: label1];
// And do not forget to release your label!
[label1 release];
}
If you want to change text of label that already exists do not create new instance in your method, just set new text to it:
-(void)setOne:(NSMutableArray *)theArray {
// if label1 already exists we don't need to create a new one
label1.text = #"Test";
}
Edit: (from more info in comments)
When you create view controller it may not load its view immediately so in your code
FirstViewController *FVC = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
[FVC setOne:[resultaten objectAtIndex:indexPath.row]];
when you call setOne method fvc's view may still not be loaded and label1 is still nil in that method. You can solve that forcing controller's view to load, the following should work:
FirstViewController *FVC = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
FVC.view;
[FVC setOne:[resultaten objectAtIndex:indexPath.row]];
But in general I'd suggest to store your values in some class that's independent from UI (i.e. Model) or at least in separate variable of your controller and set it to UI elements only when they actually loaded or appear on screen (in viewDidLoad or viewWillAppear methods)
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 200, 22)];
lbl.text =#"Hello";
[self.view addSubview:lbl];
}

UITableView section index overlaps search bar

Hi: I want to display a section index in an UITableView with a search bar in the table view header (not section header).
But the index strip is now overlapping the search bar. Is there an elegant solution to avoid this and let the index start below the table header?
I realize this answer comes very late, but I had the same problem and searched here and elsewhere. I found good answers here:
Changing the size of the UISearchBar TextField?
There are several suggestions, but the one I found most straightforward was to put a UISearchBar and UINavBar in a UIView and pass that view to setTableView. The problem is that the table controls the size of the header view, ignoring any setting you add. So adding the view makes the table happy and you can reach inside and set the search bar size without being interfered with by the table.The UINavBar has the same background styles as the UISearchBar, so fills the extra space in a visually consistent way, though you have to tweak its frame - See below:
UISearchBar searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0, 1, 290, 40)] autorelease];
UIView *searchView = [[[UIView alloc] initWithFrame:CGRectMake(0, 1, 320, 40)] autorelease];
UINavigationBar *navBar = [[[UINavigationBar alloc] initWithFrame:CGRectMake(1, -1, 320, 41)] autorelease]; // same gradient/style as search bar
[navBar setTintColor:[UIColor lightGrayColor]];
[searchView addSubview:navBar];
[searchView addSubview:searchBar];
I add empty strings to indexes array:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSMutableArray *array = [NSMutableArray arrayWithArray:_sortedKeys];
[array insertObject:#"" atIndex:0];
[array insertObject:#"" atIndex:0];
return array;
}