I my application i want to hide the UIPickerview controller when application enter's in a paused state?
for eg: in my viewcontroller i am using uipickerview,and is placed in a popovercontroller,but i have not dismiss the popovercontroller and the application goes in a paused state.
when user open the application the uipikcer view is displayed which i want to dismiss.
please help me out with this.
Use NSNotificationCenter for hide the UIPickerView when application go in background like bellow...
[[NSNotificationCenter defaultCenter] addObserver:alertView selector:#selector(HidePickerView) name:#"UIApplicationWillResignActiveNotification" object:nil];
and hide the UIPickerView in bellow method..
- (void) HidePickerView {
[yourPickerView setHidden:YES];
}
You need to subscribe for the UIApplicationWillResignActiveNotification notification and when it's fired and your selector is called, you should [self.myPickerView dismissViewControllerAnimated:NO completion:nil];.
Note: -viewWillDisappear: method would not be called when the app is resigning active.
Related
I am currently presenting a security code view controller that contains a UITextField in which the user is supposed to enter a passcode. This security code view controller is presented in its own window which has a "windowLevel = UIWindowLevelAlert + 1;" because i want to hide potential UIAlertView or other windows that could be present already displayed.
The problem comes when i call the resignFirstResponder method on the textfield, it seems that the keyboard is dismissed without the usual animation.
I tried to register to the various keyboard notification, and checked the UIView areAnimationsEnabled property and it returns YES.
So if anybody already had this issue, you're welcome :)
UIKeyboardAnimationDurationUserInfoKey is a constant string identifier the animation duration, so there is where of enabling and disabling the animation.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(willHideKeyboard:)
name:UIKeyboardWillHideNotification
object:nil];
- (void)willHideKeyboard:(NSNotification *)notification {
[UIView setAnimationsEnabled:NO];
}
I have 2 views:
OneViewController
TwoViewController
TwoViewController has an IBAction which plays a sound. Once the user has pressed the button on TWoViewController I want a UILabel which will appear on OneViewController saying that the sound has been played.
Thanks for the help
All you have to do is reference one viewController in the other one, that way you can call it's methods. Or you can simply create a delegate.
One possible solution is to use notifications.
In the action that plays a sound, post a notification to the default notification center that indicates the sound has played.
[[NSNotificationCenter defaultCenter] postNotificationName:"playSoundNotification"
object:self
userInfo:nil];
When OneViewController is created, have it register for the notification.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(showPlayedLabel:)
name:"playSoundNotification"
object:nil];
When it receives the notification -- in showPlayedLabel: -- display the UILabel. Note that showPlayedLabel must follow the appropriate signature format.
- (void) showPlayedLabel:(NSNotification*) aNotification;
I've an iPhone application:
When you open the app you see the "LoginView". If you login into application you see a TabBarController. In the third and last tab there is "Logout" button. If you click you see the "LoginView" again. My problem is that if you login again you see the "old" tabbar and the selected tab is the third and not the one, and there is a "Logout" button. Also, if a user login with a different user, see the old data of the previous user (very dangerous).
Here's the code:
- Delegate.h:
UITabBarController *tabBarController;
LoginViewController *loginView;
- Delegate.m (didFinishLaunchingWithOptions):
[self.window makeKeyAndVisible];
loginView = [[LoginViewController alloc] init];
if (YES) { /* if the user is not already logged */
[self.window addSubview:loginView.view];
}
Delegate.m (methods):
- (void)loginComplete {
[loginView dismissModalViewControllerAnimated:YES];
[window addSubview:tabBarController.view];
}
- (void)logoutComplete {
[[tabBarController view] removeFromSuperview];
[tabBarController release];
[window addSubview:loginView.view];
}
And here's the two methods in two different viewcontrollers:
- (IBAction)login:(id)sender {
TabNavisAppDelegate *delegate =
(TabNavisAppDelegate *) [[UIApplication sharedApplication] delegate];
[delegate loginComplete];
}
(the logout method is the same)
Guys, how can I solve this painful problem?
So, here's a list of application that do what I want: "Foursquare", "Brightkite" and others.
Each one have a login screen, a tabbar view and a logout button.
Thanks # everyone.
For login-logout-login situations where all kinds of things need to reset themselves at the logout or the next login, I like to create a notification, something like "NewUserReset." Everything that needs to reset itself to an original state listens for the notification and runs a method that does whatever kind of resetting it needs. The tabbar would change the button title to logout, temporary data structures nil/zero/release themselves, etc.
It's nicely decouples the logout from all of the things that have to be done so you're not trying to manipulate view controllers and data storage and view appearances from the the controller that received the logout tap.
Sending a notification is easy. When the user taps the Logout button you'll send out a notification like this:
[[NSNotificationCenter defaultCenter] postNotificationName:#"JMUserLogout"
object:nil];
You don't have to call it JMUserLogout, you just need a string that you'll recognize and something -- I used your initials -- to help ensure you don't accidentally send a notification that has the same name as a notification something you're unaware of is listening for.
When that notification goes out, any object that has registered with the defaultCenter to listen for #"JMUserLogout" will perform any actions you choose. Here's how your object registers (this should be located in some place like ViewWillLoad or the initialization method of the object):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(resetForNewUser:)
name:#"JMUserLogout"
object:nil];
The selector there, resetForNewUser:, is just the name of a method you want to run when the notification goes out. That method looks like this:
- (void)resetForNewUser:(NSNotification *)notif {
// DO SOMETHING HERE
}
Where it says // DO SOMETHING HERE you'll add the code specific to your app. For example, you can add the tab bar as an observer of the JMUserLogout notification. In its resetForNewUser: method you'd change the name of the logout button to Login.
In a ViewController or View or data store that holds old data from the previous user the resetForNewUser method would delete all of that data and set things back to the way they should be fore a new user. For example, if the previous user entered data into a UITextField you would delete the text, yourTextFieldName.text = #"";
Lastly, it's important that you also remove your object as an observer before it's deallocated. In your Dealloc method of each object that registered to receive the notification you add this:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Hopefully that makes sense. The Apple documentation for NSNotificationCenter explains more and they provide several sample apps that use notifications.
Seems like tabBarController is not getting released. [ retain count should be 1 before releasing] tabBarController might be retain somewhere. check the retain count of it.
If you want to reset the old data from the previous user after you log out.. all you have to do is reset the UITabBarController's viewControllers property.
So if you are subclassing UITabBarController the following code should restore your app to its original state.
self.viewControllers = #[self.viewControllerOne, self.viewControllerTwo, self.viewControllerThree];
From the documentation:
If you change the value of this property at runtime, the tab bar controller removes all of the old view controllers before installing the new ones. The tab bar items for the new view controllers are displayed immediately and are not animated into position.
The tabBarController object may have been retained somewhere. Try to remove that.
And use the following code for Login, Logout methods
- (void)loginComplete {
// initialize the tabBarController here. like the following
if(tabBarController == nil){
tabBarController = [[UITabBarController alloc] init];
}
[loginView dismissModalViewControllerAnimated:YES];
[window addSubview:tabBarController.view];
}
- (void)logoutComplete {
[[tabBarController view] removeFromSuperview];
[tabBarController release];
tabBarController = nil;
[window addSubview:loginView.view];
}
So that your problem will be solved.
I have an animation in viewDidLoad that runs the first time the app is launched. if you exit the app, then launch it again the animation doesn't play.
how would I go about making the animation play each and every time the app is opened,
thanks for any help
In iOS 4, pressing the home button doesn't terminate the app, it suspends it. When the app is made active again, a UIApplicationDidBecomeActiveNotification is posted. Register for that notification and initiate the animation in your handler.
Edit: Added code below.
Here's one way to do it: Have your view controller become an observer of UIApplicationDidBecomeActiveNotification in its viewWillAppear: method.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(performAnimation:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
Unregister for the notification in your view controller's viewDidDisappear: method.
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
Finally, put your animation code in the selector specified when registering to receive the notification.
- (void)performAnimation:(NSNotification *)aNotification {
// Animation code.
}
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html
Put the animation in a method like
applicationDidBecomeActive:
of UIApplicationDelegate
Very likely your app isn't quitting and reloading. By default, on iOS 4 apps continue to run when the user 'exits' the app, and continue where they left off when 'restarted'.
Take a look at applicationDidBecomeActive in your app delegate. You could kick off your animation from there when the app is deactivated.
How about set a flag in your application delegate to control this behavior:
Set it to YES when the app enters the foreground or became active (applicationWillEnterForeground:, applicationDidBecomeActive:)
Check if this flag is NO in -viewWillAppear in your view controller:
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
if(!delegate.animationPlayed) {
//perform animation here...
delegate.animationPlayed = YES;
}
I'm creating an iphone app with few elements inside the controller (e.g tab bar, uiview, uitoolbar, etc..). Everything works fine until I encountered this problem. While my application is launched, I received a call and it shows the "Call Status Bar" which ruined the ui. Some elements are pushed down because the "Call Status Bar" is taking space at the top.
Anybody here have an idea on how to fix this issue? I'm new to iPhone app development.
Your reply is greatly appreciated...
Best Regards,
dianz's solutio works just fine but is a bit redundant if you are only interested in knowing about the notification inside of a specific view controller.
After the delegate method application:didChangeStatusBarFrame: is called in the Application Delegate UIApplicationDidChangeStatusBarFrameNotification is posted through [NSNotificationCenter defaultCenter].
Instead of using the delegate method application:didChangeStatusBarFrame: to simply repost a custom notification you can add an observer to UIApplicationDidChangeStatusBarFrameNotification directly from your view controller.
In MyCustomViewController you would add something similar to this:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(doSomething:)
UIApplicationDidChangeStatusBarFrameNotification
object:nil];
Now you no longer need to define the application:didChangeStatusBarFrame: delegate method in appDelegate (unless you plan to do something in the appDelegate when the status bar changes size).
As with dianz's example you need to remove the observer in dealloc
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
You should put this function on appDelegate, this will trigger when the status bar change
- (void)application:(UIApplication *)application didChangeStatusBarFrame (CGRect)oldStatusBarFrame
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"trigger" forKey:#"frame"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"trigger" object:self userInfo:dict];
}
This Code will send Notification with the name "trigger"
Place a code to your view Controller (e.g: viewDidLoad, etc..) this listen if there are notification send with a name "trigger"
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(dataReceived:)
name:#"trigger"
object:nil];
And create a function dataReceived:
- (void)dataReceivedNotification:(NSNotification *)notification {
NSDictionary *data = [notification userInfo];
// do something with data
}
do something on this part of the code, maybe you change the frame of your tab bar, uiview frame, toolbar frame
And in dealloc, put this code to remove the observer
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
Basically what you normally do is try to set up the autoresize flags of all your ui elements in interface builder so that when the main view is "squashed" by the call status bar everything will still look reasonable. It's a little hard to explain how to do all of this in one message, but I recommend creating a view in IB, placing some subviews in it, then resizing the main view while playing with the autoresize flags to get a feel for how the flags work. The autoresize flags are in Command-3 (size inspector).
You can also set wantsFullScreenLayout in the main view controller to YES to cause the view to take up the whole screen, including the area under the status bar, but then you'll have to make sure not to place anything under the status bar and the call status bar will overlap anything too close to it, of course.
for me, whenever the status bar is enlarged, the -(void)viewWillLayoutSubviews is always called. This is perfect for me because all my subview setFrame code is in this function.