For some reason, UIKeyboardWillHideNotification is being executed twice in my below code - I haven't a clue as to why. I know this because my NSLog ("Closed!") appears twice in my console. Am I missing something obvious (and no, I don't have UIKeyboardWillHideNotification pasted somewhere in my code a second time).
-(void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillChange:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleKeyboard:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleKeyboard:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)handleKeyboard:(NSNotification*)aNotification{
NSDictionary* info = [aNotification userInfo];
NSValue* value = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval duration = 3;
[value getValue:&duration];
if (aNotification.name == UIKeyboardWillShowNotification) {
self.upView.frame = CGRectOffset(self.upView.frame, 0, -self.keyboardHeight); self.tableView.frame = CGRectOffset(self.tableView.frame, 0, -self.keyboardHeight);
[self moveCustomView:YES duration:duration];
}
if (aNotification.name == UIKeyboardWillHideNotification) {
/** KEYBOARD HIDE **/
self.upView.frame = CGRectOffset(self.upView.frame, 0, self.keyboardHeight); self.tableView.frame = CGRectOffset(self.tableView.frame, 0, self.keyboardHeight);
[self moveCustomView:NO duration:duration];
NSLog(#"CLOSED!");
}
}
Make sure to remove observers in viewDidDisappear as , view controller may be not reallocated from some reason and code in viewDidLoad is executed twice as observer is added twice
// Objective c
- (void)viewWillDisappear:(BOOL)paramAnimated{
[super viewWillDisappear:paramAnimated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
// Swift
override func viewDidDisappear(_ animated: Bool)
{
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
Be sure to remove the observer from the dealloc method. If you do not remove it and its memory is not released, it will listen for keyboard behavior on other pages. In addition, you should not add the same notification twice to the same observer.
Instead of Using same method for Hide and show notification. You can use two different Methods.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
Now, for Change your frame You can use following code
NSDictionary* info = [aNotification userInfo];
CGSize *kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
self.tableView.frame = CGRectOffset(self.tableView.frame, 0, -kbSize.height);
Please, try it like this:
What I did:
• moved subscription to viewWillAppear
• added "unsubscribe" in viewWillDisappear
• added "unsubscribe" in dealloc (shouldn't be related to your issue, but that's the right way to do it still)
• replaced == with isEqual in your handler (also not related to your issue, most likely).
There may be some typos there. Sorry, if that's the case.
-(void)viewWillAppear {
[super viewWillAppear];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillChange:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleKeyboard:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleKeyboard:) name:UIKeyboardWillShowNotification object:nil];
}
-(void)viewDidLoad {
[super viewDidLoad];
//Leaving this method here just to point out that everything was moved to viewWillAppear
}
- (void)handleKeyboard:(NSNotification*)aNotification{
NSDictionary* info = [aNotification userInfo];
NSValue* value = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval duration = 3;
[value getValue:&duration];
if ([aNotification.name isEqual: UIKeyboardWillShowNotification]) {
self.upView.frame = CGRectOffset(self.upView.frame, 0, -self.keyboardHeight);
self.tableView.frame = CGRectOffset(self.tableView.frame, 0, -self.keyboardHeight);
[self moveCustomView:YES duration:duration];
}
if ([aNotification.name isEqual: UIKeyboardWillHideNotification]) {
/** KEYBOARD HIDE **/
self.upView.frame = CGRectOffset(self.upView.frame, 0, self.keyboardHeight);
self.tableView.frame = CGRectOffset(self.tableView.frame, 0, self.keyboardHeight);
[self moveCustomView:NO duration:duration];
NSLog(#"CLOSED!");
}
}
-(void)unsubscribe {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)viewWillDisappear {
[super viewWillDisappear];
[self unsubscribe];
}
-(void)dealloc {
[self unsubscribe];
}
I basically just need to change tabs when the user taps a button on my custom UIView
This is my UIView implementation
#implementation CustomMenuView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIButton *searchButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 135.0, 40.0)];
searchButton.backgroundColor = [UIColor clearColor];
[searchButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
searchButton.titleLabel.font = [UIFont systemFontOfSize:15];
[searchButton setTitle:#"Search" forState:UIControlStateNormal];
searchButton.tag = 0;
[searchButton addTarget:self action:#selector(menuItemTapped:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:searchButton];
}
return self;
}
-(void)menuItemTapped:(UIButton*)sender{
self.tabBarController.selectedIndex = sender.tag;
}
And my ViewController class:
UIView *menuView;
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat height = [UIScreen mainScreen].bounds.size.height;
menuView = [[CustomMenuView alloc]initWithFrame:CGRectMake(0, 60, 135, height)];
[self.view addSubview:menuView];
}
This crashes because the UIView does not have a reference to the tabBarController. How do I call a method on my custom view's parent or what is the best approach to solve this?
To the best of my knowledge, you could use the delegate pattern here. So you create a protocol named CustomMenuViewDelegate and declare a weak property on CustomMenuView of this type. When the menuItemTapped: method is called you call a method on the CustomMenuViewDelegate property. You can make your ViewController conform to the delegate protocol and set is as the delegate in the viewDidLoad method.
I ended up deciding to use local notifications like this:
On my custom UIView
-(void)menuItemTapped:(UIButton*)sender{
NSDictionary* userInfo = #{#"tab": #(sender.tag)};
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:#"MenuItemSelected" object:self userInfo:userInfo];
UIViewController class
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveMenuItemSelectedNotification:)
name:#"MenuItemSelected"
object:nil];
}
-(void) receiveMenuItemSelectedNotification:(NSNotification*)notification
{
if ([notification.name isEqualToString:#"MenuItemSelected"])
{
NSDictionary* userInfo = notification.userInfo;
NSNumber* tab = (NSNumber*)userInfo[#"tab"];
NSLog (#"Successfully received test notification! %i", tab.intValue);
self.tabBarController.selectedIndex = tab.intValue;
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"MenuItemSelected" object:nil];
}
I am pretty sure this question has been asked and answered, but I am not sure what I am doing wrong that I am not being able to get the method called from NSNotificationCenter. I have two classes :
Sign In Class And Calendar View Class
I want to pass single user credential from SignIn to Calendar. I have put the Calendar in SWRevealController. NSNotification is being called but the trigger method is not called for some reason.
Sign In
- (IBAction)signIn:(id)sender {
_passWord = _password.text;
NSLog(#"%# %#",_userName,_passWord);
[[NSNotificationCenter defaultCenter] postNotificationName: #"Password" object: _passWord];
[self performSegueWithIdentifier:#"signIn" sender:self];
}
Calendar
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *ppnImage = [UIImage imageNamed:#"PPNImage.png"];
NSLog(#"came here");
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(triggerAction:) name:#"Password" object:nil];
SWRevealViewController *revealViewController = self.revealViewController;
if ( revealViewController )
{
[self.sidebarButton setTarget: self.revealViewController];
[self.sidebarButton setAction: #selector( revealToggle: )];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
events = [[NSMutableArray alloc]init];
[_indicator startAnimating];
self.tableView.delegate = self;
//Creating a background queue
web = [WebRequests sharedInstance];
web.delegate = self;
[web loginView];
}
-(void) triggerAction: (NSNotification *) notification {
NSLog(#"Does not call this");
}
Here
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(triggerAction:) name:#"Password" object:nil];
is called
BUT the below method is not called
-(void) triggerAction: (NSNotification *) notification
{
NSLog(#"Does not call this");
}
Really appreciate if somebody can suggest me what am I doing wrong
The documentation mentions adding shadows to the controller being animated to show the slide menu. However, instead of a shadow I would like to make the animated view controller to be darker. Is this possible?
I simply created a masking view and presented/removed it on notifications from the slidingviewcontroller. Added some nice fade in and fade out action for effect :) Hope this helps
#import <UIKit/UIKit.h>
UIView *overLayView;
#interface MyViewController : UIViewController {
UIView *overLayView;
}
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
overLayView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
overLayView.backgroundColor = [UIColor blackColor];
}
-(void) viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(disableView) name:ECSlidingViewUnderLeftWillAppear object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(enableView) name:ECSlidingViewTopWillReset object:nil];
}
- (void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:ECSlidingViewUnderLeftWillAppear object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:ECSlidingViewTopWillReset object:nil];
}
-(void) disableView {
overLayView.alpha = 0;
[self.view addSubview:overLayView];
[UIView animateWithDuration:0.5 animations:^{
overLayView.alpha += kViewHelperUIViewMaskAlpha;
}];
}
-(void) enableView {
[UIView animateWithDuration:0.5 animations:^{
overLayView.alpha -= kViewHelperUIViewMaskAlpha;
} completion:^(BOOL fin){
if(fin){
[overLayView removeFromSuperview];
}
}];
}
#end
I added a MPMoviePlayerController's view to my view of a viewcontroller, that i present on an iPad with UIModalPresentationFormSheet. This works fine so far, but when i tap the fullscreen button, the movie view changes to fullscreen but after the animation the modal viewcontroller appears above the view.
The only code I use is the following:
- (void)viewDidLoad
{
[super viewDidLoad];
self.player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[self.player prepareToPlay];
self.player.controlStyle = MPMovieControlStyleEmbedded;
self.player.view.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.player.view];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willEnterFullScreen) name:MPMoviePlayerWillEnterFullscreenNotification object:self.player];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didEnterFullScreen) name:MPMoviePlayerDidEnterFullscreenNotification object:self.player];
}
- (void) updateViewConstraints
{
[super updateViewConstraints];
if (!self.addedContraints) {
[self.player.view autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero];
self.addedContraints = YES;
}
}
This happens when I try to hide the viewcontrollers view.