Can't edit any objects in method - iphone

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];
}

Related

Passing data between ViewController and TabBar children

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.

Issues passing values between views on ios with storyboard

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.

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.

Passing data using UINavigationController

[I have this working, but I don't understand why my "fix" to make it work did so.]
As part of a learning exercise, I'm creating a simple table. When the user selects a cell in the table, I want it to go a second UIViewController. THe second UIViewController has a label that shows the text from the cell selected.
The "parent" class has this method to create the child & set the text:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
child = [[WDRViewControllerFirstChild alloc] initWithNibName:nil bundle:nil];
child.title = [colors objectAtIndex:indexPath.row];
child.labelText = [colors objectAtIndex:indexPath.row];
[self.navigationController pushViewController:child animated:YES];
}
Then in WDRViewControllerFirstChild, I have two methods. If I approach it this way, everything works.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 50)];
colorMap = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], nil] forKeys:[NSArray arrayWithObjects:#"red", #"green", #"blue", nil]];
// Adding the subview here won't work. Why?
// [self.view addSubview:label];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view addSubview:label];
label.text = labelText;
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor whiteColor];
self.view.backgroundColor = [colorMap objectForKey:labelText];
}
Originally, I assigned the child to the subview in the init call, however that didn't work. That is, the label of the text wouldn't properly show the text of the item that had been selected. (It would be blank.)
I added some NSLog calls and additionally found that if I move the addSubview call from viewDidLoad to the init, the value of labelText is null. However, in the form above, it's properly set.
I'm happy it's working, but I don't understand why one work & the other does. In particular, I'm really confused why setting labelText works based upon where I call addSubview.
Any insights?
-addSubview will only work if the view is actually completely loaded out of the XIB, else it sends a call to nil and produces nil. By the time -initWithNibName:bundle: is called, the OS is most likely defrosting (literally) the XIB you specified and setting it up, so the view property is nil. at -viewDidLoad you can be reasonably assured as to the existence of the view, so that's where most setup work is done. as for the (NULL) label text, whatever the iVar labelText is, you didn't instantiate it. Remove that line.

popViewControllerAnimated doesn't update info iPhone SDK

When I try to pop a view controller, it doesnt update info for the previous view. Example: I have a cell that displays text in a label in View1. When you click on the cell it goes to View2 (for example) When I choose an option in View2, popViewControllerAnimated is used to go back to View1, however, I want the label to now be updated with the new option in View1.
My dilemma is that when I pop View2, the label in View1 does not update. Any ideas? I've tried adding a [view1 reloadData]; before the view pops, but no luck.
//VIEW1 the cell that displays the label.
ringLabel = [[UILabel alloc] initWithFrame: CGRectMake(25, 12.7f, 250, 20)];
ringLabel.adjustsFontSizeToFitWidth = YES;
ringLabel.textColor = [UIColor blackColor];
ringLabel.font = [UIFont systemFontOfSize:17.0];
ringLabel.backgroundColor = [UIColor clearColor];
ringLabel.textAlignment = UITextAlignmentLeft;
ringLabel.tag = 0;
ringLabel.text = [plistDict objectForKey:#"MYOPTION"];
[ringLabel setEnabled:YES];
[cell addSubview: ringLabel];
[ringLabel release];
//VIEW2 when cell clicked
CustomProfileViewController *cpvc = [CustomProfileViewController alloc];
cpvc.ringtone = [ringList objectAtIndex:indexPath.row];
[cpvc.tblCustomTable reloadData];
[self.navigationController popViewControllerAnimated:YES];
You'll want to override -viewWillAppear: on the first view controller and update the label there. (Make sure to also call super).
Example:
- (void)viewWillAppear:(BOOL)animated {
// This method is called whenever the view is going to appear onscreen.
// (this includes the first time it appears.)
ringLabel.text = [plistDict objectForKey:#"MYOPTION"];
[super viewWillAppear:animated];
}
What is your plistDict object? How you initialize it? Are you sure, that it contains right value for your #"MYOPTION" key after the second view hides? As I can see, plistDict is an object inside your first viewController. Also I cannot see any sense in the last 4 lines of your code. They cause not reloading data but memory leak.
make sure you aren't losing anything important in your dealloc method. that messed me up for weeks. i was freeing a variable that pointed to the one in my delegate.