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.
Related
[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.
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 am currently trying to change the back button text of a subview that is loaded of a tablecell touch. However even with the way I am trying to implement it it still shows the parents title in the back button.
I am trying to load a new value into the back button inside viewdidload method like so
UIBarButtonItem *myBarButtonItem = [[UIBarButtonItem alloc] init];
myBarButtonItem.title = #"Back";
self.navigationItem.backBarButtonItem = myBarButtonItem;
[myBarButtonItem release];
however its not working.
You need to change self.navigationItem.backBarButtonItem from previous view, not current view (I know, it seems to be a little bit illogical). For example, in your table view you can do the following:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:#"My title"];
UIBarButtonItem *boton = [[UIBarButtonItem alloc] initWithTitle:#"Custom back button text" style:UIBarButtonItemStyleBordered target:self action:#selector(mySelector:)];
self.navigationItem.backBarButtonItem = boton;
[boton release];
}
This is where the documentation is not so clear until you have read and re-read and play around with each settings.
To change the title of the default back button add this line in viewDidLoad()
self.navigationController.navigationBar.topItem.title = #"Your Label";
If you want the button to be invisible - then set the value to #"" empty string.
Okay figured it out, I posted this code in the parent views tableView:didSelectRowAtIndexPath: method. this is how my one looks with multiple tablecells the user can select. Hope this helps.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
if (indexPath.section == 0) { //--- picks (first) section
ChildViewController *childViewController = [[ChildViewController alloc] initWithNibName:#"ChildViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:childViewController animated:YES];
//--- this sets the back button to "Back" every time you load the child view.
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style: UIBarButtonItemStyleBordered target:nil action:nil] autorelease];
if(indexPath.row == 0) { //--- picks row
childViewController.title = #"Bike";
}
if(indexPath.row == 1) {
childViewController.title = #"Model";
}
[vehicleSearchResponseTableViewController release];
}
}
The best way with Xcode 5 to change the back button name is to edit the Back Button field in IB of the Navigation Item on the View Controller to which the back button will return. For example, if you have a list TableViewController that goes to a detail screen, change the Back Button on the list TableViewController's Navigation item (in IB) to change the back button name that the detail screen displays.
It's not gonna work the way you're trying to do. Navigation button will always have title of previous view. What you can do though - change title of first view before pushing the new one. This is the only was I could find to solve same problem.
Your code looks fine so far.
Is this code executed before the
[super viewDidLoad];
statement (wrong) or after it (good)?
After viewDidLoad
self.navigationController!.navigationBar.backItem?.title = "Back"
My suggestion was to add a separate Label to parents Page title Bar.
Worked fine for me.
let titleLabel = UILabel(frame: CGRect(x: (view.frame.width * (3/8)), y: 0, width: (view.frame.width * 0.25 ), height:30))
titleLabel.text = "Title"
titleLabel.textAlignment = .center
titleLabel.textColor = UIColor.white
titleLabel.font = UIFont.systemFont(ofSize: 20)
navigationItem.titleView = titleLabel
This article should do what you want.
From the author:
As you can see above, all you need to do is set the leftBarButtonItem of the controller and it will hide the back button. The selector handleBack now handles the back event and you need to then manually pop the view controller off the UINavigationController’s stack. You can implement any of your own code in there, even blocking leaving the page.
A good way to do this is to set the title of the back button in the parent view controller before calling the child like this:
[self.navigationItem.backBarButtonItem setTitle:#"Your Custom Title"];
This title will be placed in the back button on the child view. The important point to get here is this title is used in the child view as the back button to the parent view.
So,
I have a form (which is basically a UITableView), and once I finish the form, I click the 'Done' button which is on top of the screen.
After clicking, I need to add the data to another tableView (which is in another tableViewController). This table is also inside a Navigation Controller.
After I press the Done Button, I need the presentModalViewController to be the new TableView (with the new data) along with the Navigation Controller on top of the tableView.
So, to summarize:
The Done Button is in someTableViewController.
I need to add an object (lets just say I am adding a a name called "Dobby" for simplicity) into another tableView called dogTableViewController.
I reload the data , and present the screen which has dogTableViewController inside the dogNavigationController.
All the classes are referenced properly and included.
I am pasting the -(IBAction) when the Done Button is clicked.
-(IBAction) doneWithData: (UIBarButtonItem*) sender{
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
[indicator sizeToFit];
indicator.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin);
indicator.tag = 1;
[self.view addSubview:indicator];
[indicator setBackgroundColor:[UIColor clearColor]];
indicator.center = self.view.center;
indicator.hidden = FALSE;
[indicator startAnimating];
if (self.dogTableViewController == nil)
{
DogTableViewController *temp = [[DogTableViewController alloc] init];
self.dogTableViewController = temp;
[temp release];
}
if (self.dogNavigationController == nil)
{
DogNavigationController *temp = [[DogNavigationController alloc] init];
self.dogNavigationController = temp;
[temp release];
}
[self.dogTableViewController.dogArray addObject:#"Dobby"];
[self.dogTableViewController.tableView reloadData];
NSLog (#"%#", [self.dogTableViewController.dogArray objectAtIndex:0]);
//Prints out "Null" //
[self presentModalViewController:dogNavigationController animated:YES];
[indicator release];
}
When I do all this and Click the Done button,
I get an empty Navigation Screen with NO TABLE in it. Plus I also had some buttons on the dogNavigationController screen. Nothings visible !!
My objective is to just transfer the screen to this new screen (which happens to be a home screen, and not the rootController). Do you think I should go with the modalViewController for this task ? Do you think I should use some other way to transfer data to another screen ?
p.s. I do not want to use PushViewController.
I think you should do
[self.navigationController popToRootViewControllerAnimated:YES];
rather. To get the root view controller, you can do,
DogTableViewController * viewController = [self.navigationController.viewControllers objectAtIndex:0];
[viewController.dogArray addObject:aDog];
Original Answer
Shouldn't you be initializing a navigation controller with the root view controller?
DogNavigationController *temp = [[DogNavigationController alloc] initWithRootViewController:self.dogTableViewController];
Situation:
I'm trying to display a loading screen while waiting for my asynchronous connection to return with data to populate the tableview.
Problem:
Creating and adding the loadingscreen works fine, however, the tableview draws its lines over it, see screenshot:
.
Code: I add the view with these lines:
-(void) viewDidLoad{
[super viewDidLoad];
_loadScreen = [[LoadScreen alloc] initWithFrame:self.view.bounds];
[self.view addSubview: _loadScreen];
[self fetchRemoteData];
}
Question: Is it possible to add the loading view ontop of the table? Or can i make sure the tableview does not draw its lines untill i call reloadData?
-Thanks in advance,
W
I've done it like this many times:
-(void) viewDidLoad{
[super viewDidLoad];
_loadScreen = [[LoadScreen alloc] initWithFrame:self.view.bounds];
[self.tableView addSubview: _loadScreen];
self.tableView.hidden = YES;
[self fetchRemoteData];
}
- (void)dataFetchedSuccessfully
{
self.tableView.hidden = NO;
}
Just hide the tableview and show it again when the data has been loaded.
There is some approaches that will solve you problem:
-Set a footer view for the table view, so all lines should disappear.
self.tableView.tableFooterView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
-I assume that you use UItableViewController. If so self.view and self.tableView both represents the same view, so by setting:
self.tableView.hidden = NO;
It will hide even your loading view. What I encoure you to do is to create a custom view which has an table view as its subview. Then you can hide this table view by only showing an loading view.
Hope I could help.