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.
Related
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.
I have a problem that i've trying to figure out for a few days now. Technically I'm trying to change a UILabel text in one view, from a trigger in a button in another view. When the button is in the view where the UILabel is, the label changes without a problem. But when assigning the trigger to a button in another view (even though using the same ViewController class) it won't change the UILabel's text.
Here's the piece of code triggering my button on both cases.
- (IBAction)getYearMonth:(UIButton*)sender {
//NSLog(#"Date: %# 1 %#", sender.titleLabel.text, self.year.text);
//evenCon.eventsCurrentDate.text = #"";
//NSLog(#"%#", evenCon.eventsCurrentDate.text);
//string = sender.currentTitle;
eventsCurrentDate.text = #"hello";
}
Excuse my knowledge in objective-c, I started learning two weeks ago.
Edit: I think i need to add this. My views are being displayed without segues, they are childs of a scrollview in the main view controller. (Kind of like the snapchat app effect)
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//FBLoginView *loginView = [[FBLoginView alloc] init];
//loginView.frame = CGRectOffset(loginView.frame, (self.view.center.x - (1)), 517);
//[self.loginView addSubview:loginView];
[self.scrollView setPagingEnabled:YES];
[self.scrollView setScrollEnabled:YES];
[self.scrollView setShowsHorizontalScrollIndicator:NO];
[self.scrollView setShowsVerticalScrollIndicator:NO];
[self.scrollView setDelegate:self];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"View1"]];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"View2"]];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"View3"]];
}
"View1" is where the label i'm trying to change is, and "View2" is where my button is.
This is happening because you are not sending any data to another view. Download Master detail sample code form Xcode (Its in add new project). Look for how they transfer data to another view controller and then display the text it in your label
You need to use setText
[_eventsCurrentDate setText:#"hello"];
I have a scrollViewController, in viewDidLoad, I add an UIImageView to it:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.scrollView addSubview:self.imageView];
}
Then I set my image:
- (void)setImage:(UIImage *)image
{
self.scrollView.zoomScale = 1.0;
self.imageView.image = image;
self.imageView.frame = CGRectMake(0,0,image.size.width,image.size.height);
self.scrollView.contentSize = self.image ? self.image.size : CGSizeZero;
}
On iPhone, this works fine, but on iPad (SplitViewController Detail), it doesn't show anything.
I think the problem is, that on iPhone ViewDidLoad is called when there is already an image set, on iPad when the app launches, the detail is always on screen.
I tried to put the addSubview to setImage, this works, but when the user clicks another item, the two imageViewControllers overlay each other.
Could anyone help me? Thanks! :-)
The basics:
viewDidLoad is only called once the controller is loaded into memory. So in your SplitViewController the viewDidLoad method is invoked immediately after launching the app.
My suggestion:
Add a UIImageView from InterfaceBuilder and connect it to your controller using a IBOutlet. This is the easiest way to reach the goal. I assume you're using a storyboard?!
right click drag the outlet to your header:
enter a name for your property and click connect
This way you can access your UIImageView in your implementation and you're good to go. No need to add it programmatically.
For further informations have a look at this tutorial: http://klanguedoc.hubpages.com/hub/IOS-5-A-Beginners-Guide-to-Storyboard-Connection
Before adding second imageViewController, you should remove first imageViewController
Try this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//_imageView variable is created by outlet, or you can do it by programmatically
_imageView.image = [UIImage imageNamed:#"1"];
}
- (void) setNewImage
{
[_imageView removeFromSuperview];
_imageView.image = [UIImage imageNamed:#"2"];
}
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 looked at the Apple appPrefs code sample, but that seems to be for navigation controllers only. I'm working with an iPad UISplitViewController that has simple root and detail VCs.
I can change certain settings (colors, date formats, etc) but currently, I have to restart the app to have the changes effected. I would prefer not to have to restart the app.
I'm using a system of loading the settings when the app starts each time. I can get a notification system to work, but I don't know how to reload the view controllers.
Any ideas how to do this (I guess reload the views somehow).
Thanks for any tips/advice. I can post some code if relevant.
If you use settings bundle to manage preferences from the Settings app:
From what you said in your question, you already know how to get a notification(UIApplicationDidBecomeActiveNotification) when your app becomes active, right?
If so, the only problem left is how to reload your view after you receive the notification. Other than UITableView, which can be easily reloaded by calling [tableView reloadData], you have to reload your view by assigning values to the UI controls that you want to reload just as you set them up initially. Say you have a UILabel label you want to reload with the newly set preference value, you just write code like this:
- (void)reloadView {
label.text = [[NSUserDefaults standardUserDefaults] stringForKey:#"PreferenceKey"];
self.view.background = …
[self.tableView reloadData];
}
- (void)reloadViewOnAppActivation:(NSNotification *)notif {
[self reloadView];
}
If you are using in app preferences setting:
If the preferences view controller does not display simultaneously with the SplitViewController. Reload your views in their controllers' viewWillAppear: methods:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self reloadView]; // See the definition of reloadView above
}
Otherwise, make the SplitViewController the delegate of, or assign it to an ivar of, the preferences view controller, and notify it of the preferences changes when appropriate — immediately after changing any single preference if you prefer in realtime update, or after all the changes are done if you prefer batch update:
// SplitViewController methods:
- (void)preferencesAreChanged {
[self reloadView]; // See the definition of reloadView above
}
// Preferences view controller methods:
// Immediate update, use a preference controlled by a `UISegmentedControl` as an example
- (void)viewDidLoad {
[super viewDidLoad];
…
[segmentedControl addTarget:self action:#selector(xPreferenceTogglingAction:) forControlEvents:UIControlEventValueChanged];
…
}
- (IBAction)xPreferenceTogglingAction:(id)sender {
// Update the x preference.
…
[delegate preferencesAreChanged];
}
// Batch update
- (void)viewWillDisappear:(BOOL)animated {
[delegate preferencesAreChanged];
[super viewWillDisappear:animated];
}
So, to help others, I will post how I (with help from Apple) solved this.
In both root and detail view controllers, I added in styles based on user settings:
"Warm Tones", "Cool Tones", "Leather" etc. These translate to code like this:
switch (styleKey) {
case 0: // BASIC
fontName = #"Copperplate";
fontSize = 16;
selectedBarColor = [UIColor lightGrayColor];
selectedTintColor = [UIColor lightGrayColor];
selectedFontColor = [UIColor darkGrayColor];
backgroundColor = [UIColor whiteColor];
selectedHighlightColor = UITableViewCellSelectionStyleGray;
backgroundImage = nil;
detailBackgroundImage = nil;
break;
Then, whenever a color/style/font is called, I used something like this:
cell.selectionStyle = selectedHighlightColor;
cell.backgroundColor = backgroundColor;
This allowed me to change the settings and styles, but I still had to restart the app each time to see the changes.
The fix turned out to be simple.
Settings the styles changed the values of the constants (e.g. fontColor) - but I wasn't actually changing the fields.
So at the end of the switch statements, all I added was something like this:
self.tableView.backgroundColor = backgroundColor;
self.navigationController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:backgroundImage]];
self.navigationController.navigationBar.tintColor = selectedBarColor;
self.tableView.separatorColor = selectedTintColor;
I had to do this in both view controllers.
Also, all this code was part of a routine (changeSettings).
This method is being observed to look for changes.
The way I handled the in-app preference look and feel (a modal VC) was to use the terrific InAppSettingsKit.
I hope this helps others. Most of you will find this a no-brainer I expect, but - having not much brain left - it took me two weeks to figure it out.