I have two views in my app and a plist file to store some values.
In the first view I've created a button called frequenciesButton that opens the second view and another button to restore the default values.
In the second view there is a pickerView and a "Done" button.
On the .m of the first view:
- (void)viewDidLoad {
[super viewDidLoad];
//
self.gameSettings = [[NSMutableDictionary alloc] initWithContentsOfFile:gameSettingsFilePath];
}
-(void)viewWillAppear:(BOOL)animated {
[self refreshView];
}
- (void)refreshView {
[self.frequenciesButton setTitle:[NSString stringWithFormat:#"%# hz and %# hz", [self.gameSettings objectForKey:#"freq-freq1"], [self.gameSettings objectForKey:#"freq-freq2"]] forState:UIControlStateNormal];
...
}
- (IBAction)setDefaultValues:(UIButton *)sender {
[self.gameSettings setValue:#880 forKey:#"freq-freq1"];
[self.gameSettings setValue:#1122 forKey:#"freq-freq2"];
...
[self.gameSettings writeToFile:gameSettingsFilePath atomically:YES];
[self refreshView];
}
When the first view is loaded, the button title is changed to the default values stored in the gameSettings dictionary. The method setTitle: works.
When I click on the frequenciesButton it opens the second view with the pickerView, I select the two new values for the freq-freq1 and freq-freq2 and it saves to the plist file on done button.
The problem is that the frequenciesButton title is not changed when the second view is dissmissed and the first view appears. The refreshView method is called but the button setTitle: does not work.
In this case, if I go back one screen, and return to this view, the button title is updated.
And when I click on defaultValuesButton, the frequenciesButton title changes. The method setTitle: also works.
Any ideas of what must be happening?
HaHA! I love that you added a link to your project.
SO!! The problem was that you have separate properties in each view to hold the data from the saved plist file, self.settings. This is fine, don't mesh them together. The requirement you had to do with this, when switching views, is to keep the ivar or properties updated as the data updates too :D
Here is how I fixed the problem:
- (void)viewWillAppear:(BOOL)animated {
self.settings = [NSMutableDictionary dictionaryWithContentsOfFile: filePath];
[self updateView];
}
I checked out the file and that was updated, but the dictionary in the TestViewController.h was not updated
I hope this was the problem :)
One problem there, not sure if it will fix it, is the fact that you have used ViewWillAppear incorrectly, you have this:
-(void)viewWillAppear:(BOOL)animated {
[self refreshView];
}
but it should be this:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self refreshView];
}
You need to invoke "[super viewWillAppear:animated];" or you will have side effects, fix that first and see what happens.
Related
I have a UITableView that i would like to hide until the user taps the button searchButtonTapped. (I'm also using this button as an IBAction.)
Originally i'm hiding the table view as you see in the viewDidLoad, and i wanna show it after the button was tapped, but it does not shown up after i tap the search button. Do i missed something? For me, it seems it should be work properly, after the button was tapped i refresh the table view.
my .h file
#property (weak, nonatomic) IBOutlet UIButton *searchButtonTapped;
- (IBAction)searchButton:(id)sender;
.m file
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.hidden = YES;
}
- (void)buttonTapped:(id)sender {
if (sender == self.searchButtonTapped) {
self.tableView.hidden = NO;
[self.tableView reloadData];
}
}
- (IBAction)searchButton:(id)sender {
[self searchSetup];
}
It's impossible to tell from the little bit of code that you posted. Add NSLog statements in your buttonTapped method that show entering the method, entering the if statement, the value of searchButtonTapped, and the value of self.tableView.
Then you can tell if the method is getting called, if the if statement is evaluating as true, and if the table view is non-nil. One of those things is likely to be the cause of your problem.
I'm guessing that the if statement is wrong. what type is the property self.searchButtonTapped? Post the code that declares that property.
Based on the name I would guess that searchButtonTapped is a boolean?
you have declared only one IBAction, which is for the method searchButton.
This method call the searchSetup´s method. What is the purpose of it?
- (IBAction)searchButton:(id)sender {
[self searchSetup];
}
So you must have another IBAction for buttonTapped method witch is currently a "void" method and not a IBAction. Or you make that connection from the storyBoard, or you must declare it programaticly like:
[self.searchButtonTapped addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]
I created a method that sets the title of a button based on a value.
This method needs to be called when opening the viewController and maybe refreshed when the controller appears again.
So i created the method and I called that method in viewDidLoad and viewDidApper but it seems to be called only when I change page and turn back to the view controller.
Why?
My code is
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self controlloRichieste];
......
}
-(void)viewDidAppear:(BOOL)animated{
[self controlloRichieste];
}
-(void)controlloRichieste{
//Numero richieste di contatto
NSString *numeroRichieste = #"1";
if([numeroRichieste isEqual:#"0"]){
[_labelRequestNumber setTitle:#"Nessuna" forState:UIControlStateNormal];
} else {
_labelRequestNumber.titleLabel.text = numeroRichieste;
_labelRequestNumber.tintColor = [UIColor redColor];
}
//Fine Numero richieste di contatto
}
You can also move that code to viewWillAppear so that it gets called each time it appears.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self controlloRichieste];
}
I see the problem now, try the other way around
-(void)controlloRichieste{
//Numero richieste di contatto
NSString *numeroRichieste = #"1";
if([numeroRichieste isEqual:#"0"]){
[_labelRequestNumber setTitle:#"Nessuna" forState:UIControlStateNormal];
} else {
_labelRequestNumber.tintColor = [UIColor redColor];
[[_labelRequestNumber titleLabel]setText:numeroRichieste];
}
//Fine Numero richieste di contatto
}
Change set the button color, before you change its titleLabel's text
I created a demo PROJECT for you, hope it's helpful!
When you open view first time the viewDidLoad is called and the viewDidAppeare.
The viewDidAppeare is called every time when the view is opened, when you push or present other view controller and go back to the maine one viewDidAppeare is called.
You should call:
[super viewDidAppear:animated];
The viewDidLoad is called just when the view is loaded and after that when it's deallocated and it needs to be allocated again. So mostly when you push or present other view controller and go back to the maine one viewDidLoad is not called.
I've got this really weird bug on my code, and I have no idea on how to solve it.
I'm using the stroryboard scheme as shown on the picture attached. One navigation controller, that performs a push segue programatically, and, when clicking the "Find" button, the "findsegue" is supposed to be performed.
So, the problem is: Randomly, the view is not loaded. viewDidLoad is executed, but nothing changes on my screen. Some other times, it all works like a charm.
Here is the code that is called when the "Find" button is pressed:
- (IBAction)encontreBtn:(id)sender {
NSLog(#"Segue is going on");
[self performSegueWithIdentifier:#"findsegue" sender:sender];
}
#"Segue is going on" is always printed.
And that's the viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"DIDLOAD");
// Do any additional setup after loading the view.
_topBar.font = [UIFont fontWithName:#"LibelSuit-Regular" size:23];
_topBar.textAlignment = NSTextAlignmentCenter;
_tableView.dataSource = self;
_tableView.delegate = self;
}
#"DIDLOAD" does print as well.
As a note, viewDidAppears runs as well.
i have a Navigation Bar, wich contains a Navigation Item, which contains 2 Bar Buttons, these are created in the Storyboard, and i wanted to change 1 of the buttons at runtime, now this works:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UINavigationItem *thisNavBar = [self myNavigationItem];
thisNavBar.rightBarButtonItem = nil; // this works, it gets removed
UIBarButtonItem *insertBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(insertSkemaItem:)];
thisNavBar.rightBarButtonItem = insertBtn; // this also works, it sets the btn
}
Now, in my other method, which is called by another controller, it does not work
- (void)callChildChange {
...
// remove old btn
UINavigationItem *thisNavBar = [self skemaNavigationItem];
thisNavBar.rightBarButtonItem = nil; // does not work?
}
There is nothing wrong with the method, it runs just fine, but the nav btn item does not get removed ?
skemaNavigationItem is a Navigation item, declared in the .h file which links the navigation item i made via the storyboard.
Your UI items need to be added to your code (by ctrl-dragging) in the header file (.h) so they can be publicly accessed from other classes/view controllers.
Presuming you've done this, hiding a UI item is best done by using
relevantClass.yourViewObject.hidden = YES;
or if you really need to delete it for good,
[relevantClass.yourViewObject.view removeFromSuperView];
Edits
Options for changing target method:
Declare #property (nonatomic, assign) BOOL myButtonWasPressed; and:
- (IBAction) myButtonPressed
{
if (!self.myButtonWasPressed)
{
// This code will run the first time the button is pressed
self.myButton.text = #"New Button Text";
self.myButtonWasPressed = YES;
}
else
{
// This code will run after the first time your button is pressed
// You can even set your BOOL property back, and make it toggleable
}
}
or
- (IBAction) myButtonWasPressedFirstTime
{
// do what you need to when button is pressed then...
self.myButton.text = #"New Button Text";
[self.myButton removeTarget:self action:#selector(myButtonPressedFirstTime) forControlEvents:UIControlEventTouchUpInside];
[self.myButton addTarget:self action:#selector(myButtonPressedAgain) forControlEvents: UIControlEventTouchUpInside];
}
- (IBAction) myButtonWasPressedAgain
{
// this code will run the subsequent times your button is pressed
}
I've got two UITextFields, the input of which I store into strings player1 and player2. These UITextFields are on a ViewController called by a popOver segue. How can I make the UITextFields keep displaying their text once the view has changed?
I tried textFieldOne.text = player1; in the viewDidLoad section of the ViewController to no avail. Any ideas?
If your loaded view's delegate isn't ViewController, your code wouldn't be executed. So be sure that your code is on the delegate of the loaded view. Use also [textFieldOne setText:player1]. It's always better to call the setter method instead of setting the ivar directly. Then be sure that your UITextField is not nil and correctly binded. Use textFieldOne = [[UITextField alloc] init] to initialise it. If your problem continues, try also [textFieldOne setText:self.player1]. Hope it helps..
EDIT :
Got the solution here. You should use NSUserDefaults so your player names are stored and can be used in each view and even after re-opening your app (if you don't want this you can erase the defaults at lunch. Here is your bunch of code you need to change :
hardOne.m :
- (void)viewDidLoad
{
[super viewDidLoad];
[hard1ON setOn:switchState animated:NO];
//read player names to user defaults
[textFieldOne setText:[[NSUserDefaults standardUserDefaults] stringForKey:#"player1"]];
[textFieldTwo setText:[[NSUserDefaults standardUserDefaults] stringForKey:#"player2"]];
}
- (IBAction) returnKey1
{
player1 = [textFieldOne text];
[players addObject:(player1)];
//set player1's name to user defaults
[[NSUserDefaults standardUserDefaults] setValue:[textFieldOne text] forKey:#"player1"];
}
- (IBAction) returnKey2
{
player2 = [textFieldTwo text];
[players addObject:(player2)];
NSLog(#"array: %#",players);
//set player2's name to user defaults
[[NSUserDefaults standardUserDefaults] setValue:[textFieldTwo text] forKey:#"player2"];
}