I'm using storyboard.
As I remeber (I worked with ios 4, long time ago=)) everytime, when View appears, calls
-(void)viewWillAppear:(BOOL)Animated {}
method.
Now this method doesn't call, if I press Home button and run app again.
How to fix it?
I need to update one UIView if it appears after home pressing.
The function viewWillAppear is not part of UIView. It is part of UIViewController.
It is called after the view controller's view has been loaded and just before it starts to transition onto screen.
If you create a subclass of UIView and put this function in it then it will never be called because it isn't supposed to be.
Edit
You are correct that viewWillAppear does not get called when the app is coming back from the background.
If you want to update a part of your app when this happens then you can do something in the AppDelegate.
I'd recommend not trying to store properties etc... in the AppDelegate though. You should do something like this...
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
// just pass the message on. In your view you will need to add an observer for this notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"UpdateViewNotification" object:nil];
}
try this, call the super,
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
Related
I've created an app that has two viewcontrollers. The app opens to a title screen (general UIViewController titled 'Title') with a segue connection to the second view that is a custom class (OSViewController titled 'MapView'). As it is, the app suspends when entered into the background state so it opens right where you left off which is typically in MapView.
I want to know what I need to do to have the app start at the title screen when it becomes active. Preferably, I'd like it to open to the title screen if it is inactive for more than 1 minute. From what I've been reading, it seems like I would make a call in applicationDidBecomeActive: method in my AppDelegate to code this in. Please provide me the code to put in the applicationDidBecomeActive: method (if that's the right place to put it) that will reopen my app to the title screen when transitioning from the inactive state to the active state. My app is almost finished but I'd like to fix this issue and I don't have a lot of experience dealing with app states. Thanks in advance for your time.
If you need more information just ask.
You can also register a class as an observer of the "didBecomeActive" notification. You should place this in the viewDidLoad or the init method of your class.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
In this case, willBecomeActive: is a method that you have defined in your class that get's called when the app becomes active again. That might look something like this:
- (void)willBecomeActive:(NSNotification *)notification {
if (self.navigationController.topViewController == self) {
[self.navigationController popToRootViewControllerAnimated:YES];
}
}
You'll also need to add this in your viewDidUnload method
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
EDIT:
Thanks #AMayes for the advice. I don't believe key/value observing is necessary in this instance.
This is the approach I am using:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.tabBarController hideTabBar];
}
-(void) viewWillDisappear:(BOOL)animated
{
[self.tabBarController showTabBar];
[super viewWillDisappear:animated];
}
With this approach if I add something to the navigation stack the UITabBar will be shown again.
What about if I want UITabBar to be only shown when user navigate away to another tab or press back button, so not all cases of viewWillDisappear?
Pushing a UIViewController on top of navigation stack shouldn't change that
You can use NSNotification as well, so whenever you require to hide tab bar. At that moment fire that notification which will show/hide your tab bar.
Benifit of NSNotification is, you can fire that in entire application life cycle, and it does not be specific to any view controller or any class. One can use that independently from any class/view controller.
Hope this is what you are looking for.
Regards,
Mrunal
Do following in your view will appear method
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.navigationController.tabBarController.tabBarController.tabBar.hidden=TRUE;
}
This will remove tabbar from the particular controller . and navigation stack will not change.
This is what I did
At viewDidDisappear, I check if self.navigationController is empty. If it's empty I simply know that the view has been poped out of navigationController, which is the only way to get that view out of window hierarchy.
What is the best way to display a view (in my case a login screen) on app resume. From looking around, I've been playing with the applicationDidBecomeActive event in my AppDelegate, but I cannot seem to get my head around how to properly display a view from here.
I've tried to grab the current window by using self.window and/or it's subviews, but from the AppDelegate self.window is nil.
So far this application seems to be wired up correctly, but I am baffled by two things.
A) why is self.window nil from within my AppDelegate's applicationDidBecomeActive event handler.
B) what is the correct/normal way of display a login view (or the like) on application resume.
Implement a custom UIViewController for all of your applications to inherent from. In this view controller implement logic in the viewWillAppear message to determine and show the login screen if necessary.
//CustomViewController.h
#interface CustomViewController : UIViewController
#end
//CustomerViewController.m
#implementation CustomViewController
-(void)viewWillAppear:(BOOL)animated{
if(login_required){
LoginViewController *loginView = [[LoginViewController alloc] initWithNibName:#"LoginView" bundle:nil];
[self presentModalViewController:loginView animated:false];
}
}
#end
Then, simply, in your login view controller make sure you call:
[self dismissModalViewControllerAnimated:false];
The benefits of this approach are two fold. Firstly, it's a very simple implementation. However, most compellingly, having a base class for an application's view controller presents the opportunity to extract common logic.
Jason,
I have worked on a security tutorial provided by Chris Lowe on raywenderlich.com that was intended to demonstrate how to use basic iOS security to lock the application.
The premise behind this tutorial though was that the application would prompt for login upon first launch and if application was resumed upon unlocking the device through the use of NSNoftificationCenter in viewDidLoad and subscribe the the notifications: deviceWillLock and deviceWillUnlock. All of this assumes the device is set to lock.
Basic iOS Security Tutorial Part 2 - This is the part that has the NSNotification registration.
Basic iOS Security Tutorial Part 1 - This is the first part of the tutorial for clarity.
I also ran into this problem and came across this question whilst researching a solution. I didn't want to create the intermediate super class for my views and I wasn't sure how it would work out with navigation controllers. I have come up with another solution that works well for me - so thought I would share it. It is based around the use of NSNotificationCenter .
In your app delegate create a property to hold a reference to the currently displayed view controller - say currentViewController.
Then in the applicationDidFinishLaunching method, register a block observer to update the currentViewController property like this:
[[NSNotificationCenter defaultCenter] addObserverForName:#"CurrentViewChanged"
object:nil
queue:nil
usingBlock:^(NSNotification *note)
{self.currentViewController = (UIViewController *)note.object;} ];
In your view controller implementations, update the viewDidAppear methods to notify the observer that a new view controller is being displayed by adding the following line
[[NSNotificationCenter defaultCenter] postNotificationName:#"CurrentViewChanged" object:self];
Finally, include code in the applicationDidBecomeActive method in your app delegate to force the modal display of your login screen.
UIStoryboard *mainStoryBoard = self.window.rootViewController.storyboard;
UnlockViewController *uvc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"modalUnlockView"];
uvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.currentViewController presentViewController:uvc animated:YES completion:NULL];
A couple of additional items to note :-
You can disable the login screen display at anytime by posting a notification where the view controller passed is nil.
You only need to post the notification once for a navigation view controller at the top level. All view controllers in the navigation controller stack will be covered. I haven't checked, but I suspect the same is true for a tab view controller.
If you want to display the login screen the first time you enter the app after startup then include the following line in the applicationDidFinishLaunching method.
self.currentViewController = self.window.rootViewController;
I hope this is of some use.
Thanks
I have an application with Textfields in my MainViewController.m file. There is also a scrollview in that file, so when the keyboard comes up, the view scrolls so the user can see the textfield. The keyboard is dismissed when the user taps on the screen. Everything is working well EXCEPT in the case that the user hits the home button to put the app in the background and then comes back to it. In this case, the keyboard is still up, but my scrollview is down with textfields hidden. Ideally I would like to have the keyboard be dismissed as well.
Having looked into it, the methods that are called are all in the AppDelegate.m file (unfortunately it does not go into ViewDidLoad or any of the View lifecycle methods). How do I dismiss the keyboard from applicationDidEnterBackground in the AppDelegate.m file?
I am kind of a newbie - I have tried making a +dismisskeyboard function in my MainViewController file and calling it from the Appdelegate, but my Textfields are all instance variables and that does not work. I have also tried to create a textfield in my AppDelegate file and then do this -
[_someField becomeFirstResponder];
[_someField resignFirstResponder];
but this also does not work... I can't figure out how to link anything on my storyboard to the AppDelegate property of someField.
Can anyone suggest the correct approach to tackle this problem?
Just register a method for UIApplicationDidEnterBackgroundNotification in your MainViewController class and dismiss your keyboard there. e.g.
Register for the notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil];
then add this method
- (void) receivedNotification:(NSNotification *) notification
{
[txtFld resignFirstResponder];
}
Im my application, I display a NSView when a user click on an icon in the systemstatusbar.
This NSView is displayed with MAAttachedWindow.
My question is : how to refresh the NSView content when the attachedWindow is displayed (makeKeyandorderFront)
I've tried to refresh the content in the awakeFromNib method,but it works only once.
Could anyone help me?
thanks
The solution I've found:
I've added a observer in my view:
I've set the object to [selft window] to listen the NSWindowDidBecomeKeyNotification notification of the MAAttachedwindow.
-(void)awakeFromNib
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:[self window]];
}
-(void) windowDidBecomeKey:(NSNotification *)note
{
// Do refresh here
}
The reason -awakeFromNib only works once is presumably because you're only loading the assembly from the xib once and keeping it around.
Presumably whatever action actually shows your view in the MAAttachedWindow instance is the ideal place to "refresh" it before display, ie your own call to -makeKeyAndOrderFront:.
So: What have you tried?