Keyboard and getting up state on iPhone - iphone

How do I find out if the keyboard is up?
I have a UISearchbar instance which becomes the first responder.
When the keyboard appears a notification is sent out as part of the API, however I don't want to respond to this right away. I could record this in a boolean state, but that seems clunky. I'd like to know if there is a "getter" some where I can call to find out.

This is how I do it:
KeyboardStateListener.h
#interface KeyboardStateListener : NSObject {
BOOL _isVisible;
}
+ (KeyboardStateListener *) sharedInstance;
#property (nonatomic, readonly, getter=isVisible) BOOL visible;
#end
KeyboardStateListener.m
#import "KeyboardStateListener.h"
static KeyboardStateListener *sharedObj;
#implementation KeyboardStateListener
+ (KeyboardStateListener *)sharedInstance
{
return sharedObj;
}
+ (void)load
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
sharedObj = [[self alloc] init];
[pool release];
}
- (BOOL)isVisible
{
return _isVisible;
}
- (void)didShow
{
_isVisible = YES;
}
- (void)didHide
{
_isVisible = NO;
}
- (id)init
{
if ((self = [super init])) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:#selector(didShow) name:UIKeyboardDidShowNotification object:nil];
[center addObserver:self selector:#selector(didHide) name:UIKeyboardWillHideNotification object:nil];
}
return self;
}
-(void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
#end
Then use this to figure out the rest:
KeyboardStateListener *obj = [KeyboardStateListener sharedInstance];
if ([obj isVisible]) {
//Keyboard is up
}

The only sure way that I can think to do it as you said. using notifications like this:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
and then
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
Other than that, you may be able to iterate through your views subviews and look for the keyboard like:
UIView *keyboard = nil;
for (UIView *potentialKeyboard in [myWindow subviews]) {
// iOS 4
if ([[potentialKeyboard description] hasPrefix:#"<UIPeripheralHostView"]) {
potentialKeyboard = [[potentialKeyboard subviews] objectAtIndex:0];
}
if ([[potentialKeyboard description] hasPrefix:#"<UIKeyboard"]) {
keyboard = potentialKeyboard;
break;
}
}
But I am not sure if this will break when the SDK changes ...
Maybe use this method and add a category to the window so that you can just always ask the window for the keyboard ... just a thought.

Related

Getting NSNotification to Work?

I'm currently trying to get NSNotification to work but I'm having some trouble.
I have two (2) ViewControllers: A. MainViewController & B. LoginViewController.
In my MainViewController I have a logout button that will send a url to my LoginViewController to load it (without showing my loginView). However, it's not working.
In my MainViewController this is what I have:
- (IBAction)logout:(id)sender {
NSURL *logoutURL = [NSURL URLWithString:#"https://myurl.com/logout"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"logoutInitiated" object:logoutURL];
}
This is what I have in my LoginViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
WebView.delegate = self;
WebView.scalesPageToFit = YES;
WebView.multipleTouchEnabled = YES;
loadCount = 0;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(submitLogout) name:#"logoutInitiated" object:nil];
}
- (IBAction)submitLogout:(NSNotification*)notification {
[WebView stopLoading];
NSURL * signOutUrl = (NSURL*)[notification object];
[self loadURL:nil withURL:signOutUrl];
}
My problem is that when I press the logoutButton nothing happens. (Using NSLogs, I see that it never triggers the next step) Thank you!!!!
This is because your method name you are passing in selector is wrong. You need to add colon : at submitLogout: suffix
Use
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(submitLogout:) name:#"logoutInitiated" object:nil];
in place of
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(submitLogout) name:#"logoutInitiated" object:nil];
Hope it helps you.
When you add self as an observer, you use the selector "submitLogout" without a semicolon! But your method has an argument, so the correct selector would be #selector(submitLogout:).
Note the SEMICOLON
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(**submitLogout:**) name:#"logoutInitiated" object:nil];
- (IBAction)logout:(id)sender
{
NSURL *logoutURL = [NSURL URLWithString:#"https://myurl.com/logout"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"logoutInitiated" object:nil userInfo:[NSDictionary dictionaryWithObjectsAndKeys:logoutURL,#"RECEIVED_URL", nil]];
}
- (IBAction)submitLogout:(NSNotification*)notification
{
[WebView stopLoading];
NSURL * signOutUrl = (NSURL*)[notification objectForKey:#"RECEIVED_URL"];
[self loadURL:nil withURL:signOutUrl];
}

NSnotifiaction doubts

I have a UISwitchcontroller in my setting page to change the image in main page. So I put a notification from setting page to main page. But only one notification I active every time, my setting page switch code look like this:
-(IBAction)_clickswitchlowlight:(id)sender
{
if(switchControll.on){
[switchControll setOn:YES animated:YES];
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_lowlighton object:nil];
}
else{
[switchControll setOn:NO animated:YES];
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_lowlightoff object:nil];
}
}
In my main page.h..I write this code:
extern NSString * const NOTIF_lowlighton;
extern NSString * const NOTIF_lowlightoff;
In .m above the implementation of main page I write this:
NSString * const NOTIF_lowlighton = #"lowlighton";
NSString * const NOTIF_lowlightoff = #"lowlightoff";
In viewwillappear I write this code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(clicklowlighton:) name:#"lowlighton" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(clicklowlightoff:) name:#"lowlightoff" object:nil];
}
Then this code for changing the image:
- (void)clicklowlighton:(NSNotification *)notif
{
[[self multiPageView] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"bgipad"]]];
}
- (void)clicklowlightoff:(NSNotification *)notif
{
[[self multiPageView] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"bglowlight#2x"]]];
}
I only get the clicklowlightoff notification, I didn't get the first notification...any missing in my code?
bind your function to event: UIControlEventValueChanged to this function
-(IBAction)_clickswitchlowlight:(id)sender
{
if(switchControll.on){
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_lowlighton object:nil];
}
else{
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_lowlightoff object:nil];
}
}

how to add done button in keypad

i need to add button done on keypad.
Apple does n't provide such felicity but some of application i found that done ,next,previous buttons.
like this.
how can i add these and how can i give click event to them.
can any one please help me.
1.Define the done button (= return key):
textField.returnKeyType = UIReturnKeyDone;
2.Add the action-listener:
[textField addTarget:self action:#selector(textFieldDoneEditing:) forControlEvents:UIControlEventEditingDidEndOnExit];
3.Define the action-event:
- (IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
Have fun!
EDIT:
Here you can find detailed instructions how to add a Toolbar with Next & Previous above UITextField Keyboard:
http://www.randomsequence.com/articles/adding-a-toolbar-with-next-previous-above-uitextfield-keyboard-iphone/
EDIT2:
Now, I have a really great example for you: "This view extends UITextView adding on top of the keyboard associated with this UITextView a toolbar with a « Done » Button"
I check the code and it is a lot of easier than the first example:
http://blog.demay-fr.net/2009/07/cocoa-how-to-add-a-toolbar-with-button-on-top-of-a-uitextview-in-order-to-add-a-dismiss-button/
EDIT3:
Hmmm, no, I doesn't test to code. But I will test it now!
1.Problem: the right initialization. If I add the UITextView in IB, initWithCoder gets called:
- (id)init {
NSLog(#"init");
if (self = [super init]) {
//register a specific method on keyboard appearence
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
NSLog(#"initWithCoder");
if (self = [super initWithCoder:decoder]) {
//register a specific method on keyboard appearence
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
NSLog(#"initWithFrame");
if (self = [super initWithFrame:frame]) {
//register a specific method on keyboard appearence
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
return self;
}
2.Problem: There's no view with the the Prefix "UIKeyboard":
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
NSLog(#"keyboardWindow = %#", keyboardWindow);
for (UIView *keyboard in [keyboardWindow subviews]) {
NSLog(#"keyboard = %#", keyboard);
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES) {
// THERE'S NO VIEW 'UIKeyboard'!!!
}
}
}
The code doesn't work, I'm sorry... I don't know why there's no view "UIKeyboard"... Maybe the first example will help you at this point and you can build your own solution.

MPMoviePlayerViewController and pinch out for full screen

i have search on the site but i haven't find the same problem as mine
when i do a pinch out on my video, the notification "MPMoviePlayerPlaybackDidFinishNotification" is called.
after, the "done" button put the video in pause and the player works badly...
I don't understand why this notification is called...
this is my code
- (id) init
{
self = [super init];
movie=[[MPMoviePlayerViewController alloc] init];
//we init the frame here and after the view rotate the video
[movie.view setFrame: CGRectMake(0, 0, 1024,768)];
return self;
}
+ (MoviePlayerManager*) getInstance
{
static MoviePlayerManager *movieSingleton;
if (movieSingleton==nil)
{
movieSingleton = [[MoviePlayerManager alloc]init];
}
return movieSingleton;
}
- (void) load:(NSURL*) a_videoFile withType:(VideoType)a_type
{
type = a_type;
[movie.moviePlayer setContentURL:a_videoFile];
switch (type) {
case VT_INTRO:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMovieFinishedCallbackIntro:) name:MPMoviePlayerPlaybackDidFinishNotification object:movie.moviePlayer];
break;
case VT_RESPONSE:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMovieFinishedCallbackResponse:) name:MPMoviePlayerPlaybackDidFinishNotification object:movie.moviePlayer];
break;
default:
NSLog(#"video Type not initialised");
break;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myMovieIsReadyToPlay:) name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification object:movie.moviePlayer];
[movie.moviePlayer prepareToPlay];
}
-(void)myMovieIsReadyToPlay:(NSNotification*)aNotification
{
[gsDelegate.view addSubview:movie.view];
[movie.moviePlayer play];
movie.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
}
- (void) myMovieFinishedCallbackIntro:(NSNotification*)aNotification
{
NSNumber* reason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
NSLog(#"%d",reason);
if(aNotification != nil)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:movie.moviePlayer];
[gsDelegate movieIntroDidStop];
}
}
the NSNumber* reason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
is the same for a pinch out or when i press "done"
thx for your help (and sorry for my bad english ;op)
NSNumber* reason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
NSLog(#"%d",reason);
NSNumber is an Objective-C object, not a primitive C type. You are displaying the pointer to the object, not the value.
Correct with:
NSLog(#"%#", reason);
OR change reason to an Integer:
int reason = [[userInfo objectForKey:#"MPMoviePlayerPlaybackDidFinishReasonUserInfoKey"] intValue];
NSLog(#"%d", reason);

How can the subView detect that the mainView is rotating?

I have a mainView. To this view, I am adding a view of the same size. When the mainView(the background) rotates, its being detected but the subview doesnt have any idea about being rotated. And its functions are not even being called. Even when the program launches too, if I am in landscape mode, its the same way.
How can I make the subView know that the device is being rotated?
Perhaps you can shoot an event from the mainView to the subView, like so (in mainView):
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
[subView didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
I quickly grew frustrated by the lack of rotation notification support for non-primary UIViewController instances.
So I baked my own as a UIViewController extension. Note that this is purely for rotation detection within the subview, it won't rotate the subview - I'm working on that part now.
Source code then example usage below.
// Released under license GPLv3.
// Copyright (c) 2012 N David Brown. All Rights Reserved.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
// Note: 'shouldAutorotateToInterfaceOrientation:' is automatically called by
// 'willRotate..', 'didRotate..' method calling notification handler
// blocks, so typically will not be desired for notification.
#define NOTIFY_SHOULD_AUTOROTATE 0
#interface UIViewController (NDBExtensions)
// For dispatchers.
#if NOTIFY_SHOULD_AUTOROTATE
-(void)notifyShouldAutorotate:(UIInterfaceOrientation)toInterfaceOrientation;
#endif
-(void)notifyWillRotate:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
-(void)notifyDidRotate:(UIInterfaceOrientation)fromInterfaceOrientation;
// For listeners.
#if NOTIFY_SHOULD_AUTOROTATE
-(void)listenForShouldAutorotate;
#endif
-(void)listenForWillRotate;
-(void)listenForDidRotate;
-(void)listenForAnyRotate;
-(void)stopListeningForAnyRotate;
#end
#implementation UIViewController (NDBExtensions)
#if NOTIFY_SHOULD_AUTOROTATE
-(void)notifyShouldAutorotate:(UIInterfaceOrientation)toInterfaceOrientation {
NSString *name = #"shouldAutorotate";
NSString *key = #"toInterfaceOrientation";
NSNumber *val = [NSNumber numberWithInt:toInterfaceOrientation];
NSDictionary *info = [NSDictionary dictionaryWithObject:val forKey:key];
[[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:info];
}
#endif
-(void)notifyWillRotate:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
NSString *name = #"willRotate";
NSString *key = #"toInterfaceOrientation";
NSNumber *val = [NSNumber numberWithInt:toInterfaceOrientation];
NSString *key2 = #"duration";
NSNumber *val2 = [NSNumber numberWithDouble:duration];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:val,key,val2,key2,nil];
[[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:info];
}
-(void)notifyDidRotate:(UIInterfaceOrientation)fromInterfaceOrientation {
NSString *name = #"didRotate";
NSString *key = #"fromInterfaceOrientation";
NSNumber *val = [NSNumber numberWithInt:fromInterfaceOrientation];
NSDictionary *info = [NSDictionary dictionaryWithObject:val forKey:key];
[[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:info];
}
#if NOTIFY_SHOULD_AUTOROTATE
-(void)listenForShouldAutorotate {
[[NSNotificationCenter defaultCenter]
addObserverForName:#"shouldAutorotate"
object:nil queue:nil
usingBlock:^(NSNotification* notification){
NSNumber *val = [[notification userInfo] objectForKey:#"toInterfaceOrientation"];
UIInterfaceOrientation toInterfaceOrientation = (UIInterfaceOrientation)[val intValue];
[self shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}];
}
#endif
-(void)listenForWillRotate {
[[NSNotificationCenter defaultCenter]
addObserverForName:#"willRotate"
object:nil queue:nil
usingBlock:^(NSNotification* notification){
NSNumber *val = [[notification userInfo] objectForKey:#"toInterfaceOrientation"];
UIInterfaceOrientation toInterfaceOrientation = (UIInterfaceOrientation)[val intValue];
NSNumber *val2 = [[notification userInfo] objectForKey:#"duration"];
NSTimeInterval duration = [val2 doubleValue];
if ([self shouldAutorotateToInterfaceOrientation:toInterfaceOrientation]) {
[self willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
}];
}
-(void)listenForDidRotate {
[[NSNotificationCenter defaultCenter]
addObserverForName:#"didRotate"
object:nil queue:nil
usingBlock:^(NSNotification* notification){
NSNumber *val = [[notification userInfo] objectForKey:#"fromInterfaceOrientation"];
UIInterfaceOrientation fromInterfaceOrientation
= (UIInterfaceOrientation)[val intValue];
UIInterfaceOrientation toInterfaceOrientation
= (UIInterfaceOrientation)[[UIDevice currentDevice] orientation];
if ([self shouldAutorotateToInterfaceOrientation:toInterfaceOrientation]) {
[self didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
}];
}
-(void)listenForAnyRotate {
#if NOTIFY_SHOULD_AUTOROTATE
[self listenForShouldAutorotate];
#endif
[self listenForWillRotate];
[self listenForDidRotate];
}
-(void)stopListeningForAnyRotate {
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"shouldAutorotate" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"willRotate" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"didRotate" object:nil];
}
#end
Example usage:
// In PrimaryViewController.h (instance of this contains 'view'
// which is first subview in window).
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
// Normal rules go here.
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
// Normal rules go here.
// ..and notification dispatch:
[self notifyWillRotate:toInterfaceOrientation duration:duration];
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
// Normal rules go here.
// ..and notification dispatch:
[self notifyDidRotate:fromInterfaceOrientation];
}
// In OtherViewController.h (this could be any non-primary view controller).
-(void)viewDidLoad {
[self listenForAnyRotate];
}
-(void)viewDidUnload {
[self stopListeningForAnyRotate];
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
// Normal rules go here.
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
// Normal rules go here.
NSLog(#"#willRotate received!");
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
// Normal rules go here.
NSLog(#"#didRotate received!");
}
You could fire an NSNotification when the main view is rotated, which the subview is registered to listen for. There's a quick overview of NSNotification over here.
One advantage of this approach is that objects other than subclasses of UIView can listen for this notification.