Can't get Secondary UITableViewController to display inside a UITabBarController - iphone

I've programmatically created a UITabBarController that is loaded in my App Delegate like this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
tabBarController = [[UITabBarController alloc] init];
myTableViewController = [[MyTableViewController alloc] init];
UINavigationController *tableNavController = [[[UINavigationController alloc] initWithRootViewController:myTableViewController] autorelease];
myTableViewController.title = #"Tab 1";
[myTableViewController release];
mySecondTableViewController = [[MySecondTableViewController alloc] init];
UINavigationController *table2NavController = [[[UINavigationController alloc] initWithRootViewController:mySecondTableViewController] autorelease];
mySecondTableViewController.title = #"Tab 2";
[mySecondTableViewController release];
tabBarController.viewControllers = [NSArray arrayWithObjects:tableNavController, table2NavController, nil];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
Now the issue I have is that I can get into the views no problem, but when I try and click onto any item in the Table View, I can't get a secondary table view to appear in any tab. The tabs work absolutely fine, just the secondary views. I'm using the code below in my myTableViewController to run when selecting a specific row (the code reaches the HELP line, and crashes)...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
// this gets the correct view controller from a list of controllers
SecondaryViewController *svc = [self.controllers objectAtIndex:row];
/*** HELP NEEDED WITH THIS LINE ***/
[self.navigationController pushViewController:svc animated:YES];
}
Simply put, I'm trying to switch views to the new view controller whilst keeping the tabs available and using the navigation to go back and forth (like in the iTunes App).

Simply put, I was creating the controller array, self.controllers, and adding objects, and then releasing the objects.
If you do not release the object until the array is released, it appears to work no problem.

You've not included in your question how you initialize the self.controllers array.
I suspect this array is not filled with initialized SecondaryViewController objects.
EDIT (Added Code example that works for me):
the .h file:
#interface FirstLevelViewController : UITableViewController {
NSArray *controllers;
}
#property (nonatomic, retain) NSArray *controllers;
#end
and the .m file:
#implementation FirstLevelViewController
#synthesize controllers;
- (void)viewDidLoad {
self.title = #"First Level";
NSMutableArray *array = [[NSMutableArray alloc] init];
// Disclosure Button
DisclosureButtonController *disclosureButtonController =
[[DisclosureButtonController alloc]
initWithStyle:UITableViewStylePlain];
disclosureButtonController.title = #"Disclosure Buttons";
disclosureButtonController.rowImage = [UIImage
imageNamed:#"disclosureButtonControllerIcon.png"];
[array addObject:disclosureButtonController];
[disclosureButtonController release];
// deleted further adds to array ...
self.controllers = array;
[array release];
[super viewDidLoad];
}

Related

Passing data from one view controller to other view controller through xib file

I want to make one app and it include form submition . In this i create one new project by single view application. In this firstViewController I have put button and by pressing it , it redirect to secondViewController.
In this i have a form. and want to take data from user and by submit button i want to redirect this to thirdViewController and want to print the form data on thirdViewController.
In firstViewController.m file i have written
-(IBAction)nextVCButton:(id)sender
{
SecondViewController *tempView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
NSLog(#"name : %#",self.nameTextField.text);
tempView.fullName = self.nameTextField.text;
[tempView setFullName:self.fullName];
[self.view addSubview:tempView.view];
}
In SecondViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"received info %#", [self.fullName description]);
self.nameLabel.text = [self.fullName description];
}
In log i am getting (name :) value but in secondViewController received info is null.
I am doing this all by using xib file. No use of Storyboard.
Please help me to get this form data to secondViewController.
Thanks.
Sorry , I couldn't get why you have done these two line code :
tempView.fullName = self.nameTextField.text;
[tempView setFullName:self.fullName];
Instead ,
Make a property of NSString in Second View Controller's .h file
#property (nonatomic,retain) NSString *strFullName;
and synthesize in .m file.
#synthesize strFullName;
Now ,
-(IBAction)nextVCButton:(id)sender
{
SecondViewController *tempView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
NSLog(#"name : %#",self.nameTextField.text);
tempView.strFullName = self.nameTextField.text;
[self.view addSubview:tempView.view];
}
I think you need to use Navigation controller if you want to navigate from one view controller to another view controller. well here you need to do property- synthesize the iVar "fullName" in ThirdViewController. and retain the value in SecondViewController .
1. ThirdViewController.h
#property(nonatomic, retain) NSString *fullName;
2. ThirdViewController.m
#synthisize fullName;
dealloc {
[fullName release];
}
3. SecondViewController.m
-(IBAction)nextVCButton:(id)sender
{
SecondViewController *tempView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
NSLog(#"name : %#",self.nameTextField.text);
tempView.fullName = self.nameTextField.text;
[tempView setFullName:self.fullName];
[self.view addSubview:tempView.view];
}
try presentViewController method instead of addSubview....
-(IBAction)nextVCButton:(id)sender
{
SecondViewController *tempView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
NSLog(#"name : %#",self.nameTextField.text);
tempView.strFullName = self.nameTextField.text;
[self.view addSubview:tempView.view];
[self presentViewController:tempView animated:YES completion:nil];
}

Populate Table With Help of PopOverController - Objective C

I am using a UIButton, on clicking it I want to display the contents that are present in my NSMutableArray in UITableView with the help of UIPopOverController i.e. I want a UITableView to pop up whose cells show the contents of my NSMutableArray.
I am using the following lines of code:
UITableViewController *table= [[UITableViewController alloc]init];
table.delegate = self;
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:table];
self.popoverController = popover;
popoverController.delegate = self;
NSString *hDir = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *hFilePath = [hisDir stringByAppendingPathComponent:#"hhhh.txt"];
NSArray *array = [NSArray arrayWithContentsOfFile:hFilePath ];
NSMutableArray *kkkk = [[NSMutableArray alloc] init];
for (NSDictionary *dict in array) {
[kkkk addObjectsFromArray:[dict allKeys]];
}
table = [[UIImageView alloc] initWithFrame:[window bounds]];
// Set up the image view and add it to the view but make it hidden
[window addSubview:table];
table.hidden = YES;
[window makeKeyAndVisible];
I am unable to get the UITableView to pop up on the press of my UIButton. Can anyone help me to sort it out?
One way to show the UITableView in the UIPopOverController is by creating a new UIViewController class. And invoking it in initWithContentViewController method of UIPopOverController.
1. Create a new UIViewController or UITableViewController class. Create an instance of it.
2. Use the instance in the initWithContentViewController method of UIPopOverController.
3. Mention from where it should "pop"
For Example in your Button action :
-(IBAction)yourButtonAction:(id)sender
{
YourNewViewController*newVC=[[YourNewViewController alloc]init];
UIPopoverController*somePopOver=[[UIPopoverController alloc]initWithContentViewController:catergoryVC]; //Tell which view controller should be shown
[somePopOver setPopoverContentSize:CGSizeMake(200, 200)]; // set content size of popover
[somePopOver presentPopoverFromRect:yourButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES]; //From where it should "pop"
}
It seems you want to present it from a UIBarButtonItem so instead of presentPopoverFromRect use presentPopoverFromBarButtonItem
[somePopOver presentPopoverFromBarButtonItem:yourBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
If you want to display popover on press of button click, then first add your button in viewcontroller, display that view controller as follows:
In app delegate write code:
MyViewController *viewController = [[MyViewController alloc] init];
[self.window addSubView:viewController.view];
In MyViewController add button and provide target to that button displayPopup as follows:
-(void)displayPopup:(id)sender
{
UITableViewController *tblViewPopover = [[UITableViewController alloc] init];
tblViewPopover.tableView.delegate = self;
tblViewPopover.tableView.dataSource = self;
tblViewPopover.tableView.backgroundColor = [UIColor whiteColor];
tblViewPopover.tableView.separatorStyle= UITableViewCellSeparatorStyleSingleLine;
float theWidth = 280;
tblViewPopover.contentSizeForViewInPopover = CGSizeMake(theWidth,200);
if(m_popOvrController){
[m_popOvrController dismissPopoverAnimated:NO];
[m_popOvrController release];
m_popOvrController=nil;
}
m_popOvrController = [[UIPopoverController alloc] initWithContentViewController:tblViewPopover];
[tblViewPopover release];
[m_popOvrController presentPopoverFromRect:sender.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
}
and you can use tableview delegate methods to display data in tableview.
I think, UIPopoverViewController is initialized using UIViewController and here you are using UIView(UITableView).
Can you please try using UITableViewController instead?
Also, if things does not work according to plan when you create it using the code try using an XIB explicitely.
This should help.

How to Display title for uitabbarcontroller

I have created uitabbarview controller using the below code
In the uitabbar controller i want to display tile for every view
Please let me know how to add title for each view ( tab bar item )
myTabBarController = [[UITabBarController alloc] init];
MyDialerViewController *aDialerViewController = [[MyDialerViewController alloc]init];
MyCallLogViewController *aCallLogViewController = [[MyCallLogViewController alloc] init];
TemplateViewController *aTemplateViewController = [[TemplateViewController alloc] init];
NSArray* controllers = [NSArray arrayWithObjects:aDialerViewController, aCallLogViewController, aTemplateViewController, nil];
myTabBarController.viewControllers = controllers;
myTabBarController.delegate = self;
myTabBarController.selectedIndex = 0;
[controllers release];
[aDialerViewController release];
[aCallLogViewController release];
[aTemplateViewController release];
[self.window addSubview:myTabBarController.view];
[self.window makeKeyAndVisible];
I set the title of the navcontroller directly in the appDelegate.
aDialerViewController.title = NSLocalizedString(#"Dialer Title", #"Dialer Title");
aCallLogViewController.title = #"Title";
aTemplateViewController.title = #"Title";
I'd also set it in the viewDidLoad method of those viewControllers.
Works fine for me. Remember to localize, just incase you need it in the future. (if not intended to, you should look into it)
self.viewcontroller.tabBarItem = // a UITabBarItem instance
Make an instance of UITabBarItem
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITabBarItem_Class/Reference/Reference.html#//apple_ref/doc/c_ref/UITabBarItem
(id)initWithTitle:(NSString *)title image:(UIImage *)image tag:(NSInteger)tag
You could write that in the initializer function of each viewcontroller.

Return NSDictionary data from popup tableview

I have a popup tableview (ViewController2) appearing when I click a button on ViewController1. Then when I select a row in the table, I want those values to be sent back to ViewController1. I have a NSDictionary set up. It works fine in a regular navigation controller, but trying to do it with dismissModalViewControllerAnimated, so the tableview drops back down, and the data is appearing in the first view.
This is similar to this question here I think: http://www.iphonedevsdk.com/forum/iphone-sdk-development/39995-return-data-dismissmodalviewcontrolleranimated.html
Here is my code:
ViewController1.h:
#protocol ViewController1Delegate;
#interface ViewController1 : UIViewController <ViewController2Delegate> {
id <ViewController1Delegate> delegate;
}
#property (nonatomic, assign) id <ViewController1Delegate> delegate;
#end
#protocol ViewController1Delegate
- (void)viewController1DidFinish:(ViewController1 *)controller;
#end
ViewController1.m:
-(void)buttonGoToViewController2 {
ViewController2 *controller = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
// this controller.delegate = self causes it to crash if i have it uncommented for some reason...
// controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:controller animated:YES];
[controller release];
}
ViewController2.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(searching) {
// Navigation logic may go here. Create and push another view controller.
NSDictionary *selectedCountry = [self.copyListOfItems objectAtIndex:indexPath.row];
ViewController1 *dvController = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil andDictionary: selectedCountry];
NSLog(#"selected hit this %#",selectedCountry);
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
[self dismissModalViewControllerAnimated:YES];
}
else {
// Navigation logic may go here. Create and push another view controller.
NSDictionary *dictionary = [self.listOfItems objectAtIndex:indexPath.row];
ViewController1 *dvController = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil andDictionary: dictionary];
NSLog(#"normal hit this %#",dictionary);
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
}
}
In your ViewController2 code you are creating a new ViewController1 object and giving it your NSDictionary. When you dismiss ViewController2 you go back to the original ViewController1, which never went anywhere and was never sent the NSDictionary. You need to provide ViewController2 with access to the ViewController1 object that presented it (I suggest doing it via a delegate pattern) in order to set the NSDictionary there.

tabBarController memory leak

In my AppDelegate I initiate a tabBar Controller, to which a bunch of navigationController is added as tabs. I use the following code:
// Init tabBar Controller
tabBarController = [[[UITabBarController alloc] init] retain];
// Init Root Views of navigation controllers
FirstRootViewController* firstViewController = [[[FirstRootViewController alloc] init] autorelease];
SecondRootViewController* secondViewController = [[[SecondRootViewController alloc] init] autorelease];
ThirdRootViewController* thirdViewController = [[[ThirdRootViewController alloc] init] autorelease];
// Init Navigation controllers of tabs
UINavigationController* firstNavController = [[[UINavigationController alloc] initWithRootViewController:firstViewController] autorelease];
UINavigationController* secondNavController = [[[UINavigationController alloc] initWithRootViewController:secondViewController] autorelease];
UINavigationController* thirdNavController = [[[UINavigationController alloc] initWithRootViewController:thirdViewController] autorelease];
firstNavController.navigationBar.barStyle = UIBarStyleBlack;
secondNavController.navigationBar.barStyle = UIBarStyleBlack;
thirdNavController.navigationBar.barStyle = UIBarStyleBlack;
// Create array for tabBarController and add navigation controllers to tabBarController
NSArray *navigationControllers = [NSArray arrayWithObjects:firstNavController, secondNavController, thirdNavController, nil];
tabBarController.viewControllers = navigationControllers;
[window addSubview:tabBarController.view];
And the dealloc function:
- (void)dealloc {
[window release];
[tabBarController release];
[super dealloc]; }
firstNavController are the navigation controllers to be added which are properly released altogether a few lines later (they are created using alloc).
TabBarController is a class variable which has been created using #property (nonatomic, retain) and #synthesize tabBarController. It receives a release command in the dealloc method.
Now instruments tells me that I have two memory leaks on the line with "tabBarController.viewControllers = navigationController".
I have tortured my head, yet I don't see why: From my understanding, navigationControllers should get released automatically and if I send it a release command a few lines later, the app crashes, so I guess I am right.
Any guesses whats wrong?
Thanks a lot!
Firstly, your tabBarController class variable has it's reference count increased twice. Once from the alloc and once from the retain in the first line of your code, yet is only released once in dealloc This is probably where your memory leak is coming from.
Secondly, although you have declared a matching #property(nonatomic, retain) tabBarController (and implemented via #sysnthesize) you are not actually using the property accessors (and its corresponding retain & release behaviour during assignment) To do this you need to use self.tabBarController rather than just tabBarController which will refer to the class variable, not the property.
Try modifying your code to the following to see if this solves your problem
// Init tabBar Controller
UITabBarController* tbc = [[[UITabBarController alloc] init];
self.tabBarController = tbc;
[tbc release];
...
- (void)dealloc {
[window release];
self.tabBarController = nil;
[super dealloc]; }