I have 2 UIViewControllers and I can pass values between them with no problem. The problem comes when I try to pass a value to a third view (a UITableViewController).
Here is my code
All the connections are set correctly, the tableview gets called here:
- (IBAction)goToTableView:(id)sender {
TableMovieViewController *vc=[self.storyboard instantiateViewControllerWithIdentifier:#"TableMovieViewController"];
vc.finalResult.text=stringFromFirstView;
[self presentViewController:vc animated:YES completion:nil];
}
The vc.finalResult.text has by example "Test Call", I verified and the value is there.
Now on the table view file:
.h file:
#property(strong, nonatomic)UITextField *finalResult;
.m file:
#synthesize finalResult;
- (void)viewDidLoad
{
[super viewDidLoad];
UINavigationBar *nav = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:finalResult];
[nav pushNavigationItem:navItem animated:FALSE];
[self.view addSubview:nav];
}
The finalResult never gets set with the value passed from the previous view.
Any ideas
Thanks
Rodrigo
Change:
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:finalResult];
With:
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:finalResult.text];
finalResult is of type UITextField and not NSString.
initWithTitle: asks for a NSString and not a UITextField as you are setting now.
EDIT:
As I read the edit that was meant as a comment on my answer you say that the UITextField *finalResult is a nil-value. This is probably because you did not allocate and ininitialise the UITextField as you should.
You need to do the finalResult = [[UITextField alloc] init]; at least BEFORE the place you set the text of it. I suggest you do it in the init function of the UITableViewController.
Related
I am developing an application which has a a TableView. When I press any cell the app goes to the next ViewController. In this viewController I have created a TabBarController by code which has 3 children ViewControllers. So, I want to pass a variable from the TableView to the Children of the TabBar. I can pass the variable to the TabBar, I have watched it with the NSlog function. It is really weird for me that in the children ViewControllers I also have type a NSlog and the variable is null, but in the output I see first this.
2013-10-01 03:01:40.687 Prototype[38131:c07] proId (null) // This is the children log from vc2 ViewController "YPProjectViewController"
2013-10-01 03:01:40.697 Prototype[38131:c07] projectID 433 // This is the TabBar LOG YPTabBarViewController
Does somebody know why I can first the Children NSLog? Maybe there is the solution.
#import "YPTabBarViewController.h"
#import "YPProjectViewController.h"
#import "YPCommentsViewController.h"
#import "YPProposalsViewController.h"
#interface YPTabBarViewController ()
#property (nonatomic,strong)UITabBarController *tabBar;
#end
#implementation YPTabBarViewController
#synthesize tabBar;
#synthesize projectId = _projectId;
- (void)viewDidLoad
{
[super viewDidLoad];
[self setUpTabBar];
}
// Set up tabBar
-(void)setUpTabBar
{
YPCommentsViewController *vc1 = [[YPCommentsViewController alloc] init];
vc1.title = #"Comments";
vc1.view.backgroundColor = [UIColor clearColor];
UINavigationController *contentNavigationController = [[UINavigationController alloc] initWithRootViewController:vc1];
YPProjectViewController *vc2 = [[YPProjectViewController alloc] init];
vc2.title = #"Project";
vc2.view.backgroundColor = [UIColor clearColor];
vc2.proId = _projectId;
NSLog(#"PROJECT ID %#", vc2.proId);
// UINavigationController *contentNavigationController2 = [[UINavigationController alloc] initWithRootViewController:vc2];
YPProposalsViewController *vc3 = [[YPProposalsViewController alloc] init];
vc3.title = #"Proposal";
vc3.view.backgroundColor = [UIColor clearColor];
UINavigationController *contentNavigationController3 = [[UINavigationController alloc] initWithRootViewController:vc3];
tabBar = [[UITabBarController alloc] init];
tabBar.viewControllers = #[contentNavigationController,vc2,contentNavigationController3];
tabBar.selectedIndex = 1;
[tabBar.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
[tabBar willMoveToParentViewController:self];
[self addChildViewController:tabBar];
[tabBar didMoveToParentViewController:self];
[self.view addSubview:tabBar.view];
}
In terms of understanding the problem, your NSLog statement in the "tab bar controller" is logging the value of vc2.proID immediately after setting it. But your NSLog output show us that that second tab's view controller is logging its results before that. That's why it's nil when the second tab's view controller's viewDidLoad logs it, because that log is happening before the tab bar controller had a chance to set the value and log it itself.
So, there are a couple of ways you could fix this:
Right before your assignment of vc2.proId, you have an innocuous line of code that says:
vc2.view.backgroundColor = [UIColor clearColor];
That line of code triggers the second view controller's view to be loaded (and its viewDidLoad will be called). If you move the assignment of vc2.proId to before you start accessing any of vc2's views, that will change the order that your NSLog statements appear (or, much better, move the setting of the background color into viewDidLoad of the child controllers).
You could just create your own init method that accepts the project id as a parameter. That would also ensure that it's set before viewDidLoad. Thus, YPProjectViewController could have a method such as:
- (id)initWithProjectId:(NSString *)projectId
{
self = [self init];
if (self)
{
_proId = projectId;
}
return self;
}
Two unrelated observations regarding the custom container calls:
When you call addChildViewController, it calls willMoveToParentViewController for you. So you should remove the call to willMoveToParentViewController. See the documentation for that method.
You might even want to retire these custom container calls altogether, and just make YPTabBarViewController a subclass of UITabBarController, itself, rather than UIViewController. That eliminates the need to custom container calls altogether. Clearly, if you have other needs for the custom container, then feel free, but it's redundant in this code sample.
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.
When pressing infobutton it is not displaying ModalView
UIBarButtonItem *infoItem = [[UIBarButtonItem alloc]
initWithTitle:#"Info"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(displayModalView:)];
- (void)displayModalView
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[Infoviewcontroller alloc] init];
UINavigationController *navigationController=[[UINavigationController alloc] init];
navigationController.navigationBar.tintColor = [UIColor brownColor];
[navigationController pushViewController:_viewController animated:YES];
[_window addSubview:navigationController.view];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
}
Anyone can help me please what is the problem in this.
Thanks a lot in advance for helping me out
In your question you didn't specify how you created your objects (the toolBar and the buttons on it), are you creating them from Xcode by dragging and dropping or from pure code, therefore I will try to point out the common issues for both cases.
First, I am assuming that you are using Xcode and dragging the components that you like. In this case you need to create in the .h file an Outlet that will be linked to the button on the bar as follows:
#interface yourViewController : UIViewController
{
UIBarButtonItem *barButton;
}
#property (nonatomic, retain) IBOutlet UIBarButtonItem *barButton;
- (void) barButtonPress;
Notice that I added a function that will handle the bar button press. Now you need to link this Outlet to the bar button item, simply in Xcode in the Connection Inspector where it says New Referencing Outlet drag to the File's Owner box (the yellow cube).
Now in the viewDidLoad add the following:
[barButton setTarget:self];
[barButton setAction:#selector(barButtonPress)];
This code will link your bar button to the function that you want to be called when you press it. Now for the view that you like to view Modal, I assume that you already #import it also in the .h file, lets call it MyViewModal.
Inside the function that will be called when you press the bar button:
- (void) barButtonPress
{
MyViewModal *myViewModal = [[MyViewModal alloc] initWithNibName:#"MyViewModal" bundle:nil];
[self presentModalViewController:myViewModal animated:YES];
}
That's all, it will be displayed in Modal View. Keep in mind the allocating the new view is done based on your needs, here I did the simplest case just for illustration.
UPDATE: If not using Xcode
If you are not using Xcode then you should have a toolbar already defined say it is named myToolBar. To add buttoms to the tool bar we use the myToolbar.items way therefore we need to prepare the buttons with their targets before adding them. Here is a workflow:
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:self action:#selector(barButtonPress) forControlEvents:UIControlEventAllEvents]; //same function as above
UIBarButtonItem *btn = [[[UIBarButtonItem alloc] initWithCustomView:infoButton] autorelease];
myTool.items = [NSArray arrayWithObjects:btn, nil];
This should do it for you.
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];
}
I'm trying to create a tableview with a searchbar inside the header view of the table. I'd like to use a searchDisplayController to manage everything.
I've created everything programmatically (I'm not feeling comfortable with IB) trying to set all the correct properties, but it seems that I'm missing something, because when the table shows up I'm not able to edit the text in the searchbar and see any animation.
Here is a part of the code:
- (void)viewDidLoad {
[super viewDidLoad];
UISearchBar *searchBarTMP=[[UISearchBar alloc]init];
self.searchBar=searchBarTMP;
[searchBarTMP release];
self.searchBar.autocapitalizationType=UITextAutocapitalizationTypeNone;
self.searchBar.delegate=self;
self.searchBar.showsScopeBar=YES;
self.searchBar.keyboardType=UIKeyboardTypeDefault;
self.searchBar.userInteractionEnabled=YES;
self.searchBar.multipleTouchEnabled=YES;
self.searchBar.scopeButtonTitles=[NSArray arrayWithObjects:NSLocalizedString(#"City",#"Scope City"),NSLocalizedString(#"Postal Code",#"Scope PostalCode"),nil];
self.tableView.tableHeaderView=searchBar;
self.searchBar.selectedScopeButtonIndex=0;
self.navigationItem.title=NSLocalizedString(#"Store",#"Table title");
//SearchDisplayController creation
UISearchDisplayController *searchDisplayControllerTMP = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchDisplayController=searchDisplayControllerTMP;
[searchDisplayControllerTMP release];
self.searchDisplayController.delegate=self;
self.searchDisplayController.searchResultsDelegate=self;
self.searchDisplayController.searchResultsDataSource=self;
//....continue
}
I know that when you use a searchbar alone you must deal with its delegate protocol, but I'm guessing that the searchDisplayController manage for you as seen in the Apple sample code. (build up with IB).
Any suggestion?
Thank you,
Andrea
Found it...
After putting in the header of the table view must write
[self.searchBar sizeToFit];
If you are using ARC, make sure you create an iVar for the UISearchDisplayController in your header file.
If you create an UISearchDisplayController using:
UISearchDisplayController* searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchField contentsController:self];
it will get released by ARC, it will not call any delegate methods and when you'll call self.searchDisplayController (the UIViewController's property) it will be nil.
So, the fix is:
In your header (.h) file:
#interface MenuViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate> {
UISearchDisplayController* searchDisplayController;
UISearchBar *searchField;
UITableView* tableView;
NSArray* searchResults;
}
and in the implementation (.m) file:
searchField = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 49)];
searchField.delegate = self;
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchField contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
searchDisplayController.searchResultsDelegate = self;
tableView.tableHeaderView = searchField;
tableView.contentOffset = CGPointMake(0, searchField.frame.size.height);
When implemented like that, you can call both self.searchDisplayController and searchDisplayController in the rest of your code.