Is there a way to catch an WillRotateToInterfaceOrientation event from an UIView? - iphone

every UIViewController has a method called willRotateToInterface.
Is it possible to do this within a UIView too?
Does this match the idea of model view controller ?
The only way I can think of is to send the event from the UIViewController to the UIView.
Is there a global variable for the current orientation?

Observe UIDeviceOrientationDidChangeNotification:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
...
- (void)orientationDidChange:(NSNotification *)note
{
NSLog(#"new orientation = %d", [[UIDevice currentDevice] orientation]);
}
UIDevice Class Reference
I should note that yo uneed to add -beginGeneratingDeviceOrientationNotifications when you want these notifications to be sent, and call -endGeneratingDeviceOrientationNotifications when you want them to stop. There is a battery impact of generating these, so you should only do so when your view is on screen. UIViewController does all this for you, so if you have a view controller, it is worth letting it do the work.

If you just want to adjust view to new size/layout when orientation changes, you should just override its layoutSubviews method.
It will be called whenever size of the view changes, which usually happens when view is rotated.

You can subscribe to a global notification and get a call when the device is rotated, it wont do anything for you though..
[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification" object:nil];

Related

UIKeyboardDidHideNotification error application crashing

I'm using a UIView. The application is using ARC. UIView is used in multiple view controllers. In UIView a listener to the UIKeyboardDidHideNotification is added. The listener works fine with some view controllers and with other view controllers it crashes the application. Especially when I use in the second view contoller after using in the first. The error is
* -[appname keyboardWillHide]: message sent to deallocated instance 0xb9c2760
In some scenarios the listener is getting called twice.
The code i have added in the uiview drawrect method is:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil];
the code for listener is
-(void)keyboardWillHide
{
if(boolisViewlifted)
{
CGRect newFrame=self.frame;
newFrame=CGRectMake(self.frame.origin.x, self.frame.origin.y+250, self.frame.size.width, self.frame.size.height);
self.frame=newFrame;
boolisViewlifted=false;
}
}
The uiview appears on top of the calling view controller. Please let me know what causes this error and how to solve it.
Your view is getting unloaded because of memory warnings. You need to override dealloc method & remove observer for all notifications in all views where you added observer for notifications.
//do add in all views
-(void)dealloc
{
//[super dealloc];//As you are using ARC don't call super's dealloc
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

No orientation-related notifications are being fired. Why?

I want to be notified when the orientation of the device changes. I've setup a test method that's suppose to receive the notification. I'm trying several different observers to achieve that, and none of them are working. Why isn't testMethod being fired?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
// register for orientation change notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(testMethod) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(testMethod)
name: UIApplicationWillChangeStatusBarOrientationNotification
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(testMethod)
name: UIApplicationDidChangeStatusBarOrientationNotification
object: nil];
}
- (void)testMethod
{
NSLog(#"phone was rotated");
}
I accidentally had the rotation lock engaged on my phone. Always test on more than one phone!
You need to use the Orientation notification, which is UIDeviceOrientationDidChangeNotification. Do not put it inside the #"UIDeviceOrientationDidChangeNotification" because you dont know the actual content of the constant which is UIDeviceOrientationDidChangeNotification. It appears you are using a view controller. You should use willRotateToInterfaceOrientation:duration: and didRotateFromInterfaceOrientation:
end of the bool type something set the orientation .write return yes in all end of the view ..orientation in potrait and landscape mode takeplace

How to get Rotation events on ViewController within UITabBarController->UINavigationController?

I wanna show a full-screen Landscape view whenever the user rotates the iOS device from portrait to landscape, where the portrait view is a view within a TabBar and NavigationController.
However, willRotateToInterfaceOrientation:duration: is never called. I tested also to add the ViewController as Observer of UIDeviceOrientationDidChangeNotification events, but this notification is called also with undefined orientation.
What would be the best and easiest way for the given task?
There are also UIApplicationWillChangeStatusBarOrientationNotification and UIApplicationDidChangeStatusBarOrientationNotification notifications.
The userInfo dictionary contains an NSNumber object that encapsulates a UIInterfaceOrientation value. Use UIApplicationStatusBarOrientationUserInfoKey to access this value
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
- (void) didRotate:(NSNotification *)notification{
NSNumber *num = [[notification userInfo] objectForKey:#"UIApplicationStatusBarOrientationUserInfoKey"];
NSLog(#"%d", [num intValue]);
}

Can I watch an NSNotification from another class?

I'm trying to get my head around NSNotificationCenter. If I have something like this in my App Delegate:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(something:)
name:#"something"
object:nil];
-----
-(void)something:(NSNotification *) notification
{
// do something
}
Can I somehow watch this in another view controller? In my case, I'd like to watch it in a view controller with a table, and then reload the table when a notification is received. Is this possible?
Yes you can do it like this:
In class A : post the notification
[[NSNotificationCenter defaultCenter] postNotficationName:#"DataUpdated "object:self];
In class B : register first for the notification, and write a method to handle it.
You give the corresponding selector to the method.
//view did load
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleUpdatedData:) name:#"DataUpdated" object:nil];
-(void)handleUpdatedData:(NSNotification *)notification {
NSLog(#"recieved");
}
Yes you can that is the whole purpose of NSNotification, you just have to add the View Controller you want as an observer exactly the same way you did on your App Delegate, and it will receive the notification.
You can find more information here: Notification Programming
Of course it's possible, that's the whole point of notifications. Using addObserver:selector:name:object: is how you register to receive notifications (you should do this in your table view controller), and you can use postNotificationName:object:userInfo: to post a notification from any class.
Read Notofication Programming Topics for more info.
You can register to observe notifications in as many classes as you like. You simply need to "rinse and repeat". Include the code to register as an observer in your view controller (perhaps in viewWillAppear:) and then reload the tableView from your method:
- (void)viewWillAppear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(something:) name:#"something" object:nil];
}
-(void)something:(NSNotification *) notification
{
[self.tableView reloadData];
}
It's also a good idea to de-register the view controller once you no longer need the notifications:
- (void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
You should just add that as an Observer and give a different selector method if you want that viewController to behave differently when that notification is posted.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(somethingOtherThing:)
name:#"something"
object:nil];
-(void)somethingOtherThing:(NSNotification *) notification
{
// do something
}

Pass An Object Between 2 View Controllers

I'm trying to pass an object between 2 VCs, from a popover to the detail view of split view controller.
I think I need to use NSNotificationCenter.
I tried this but can't seem to get it to work.
In didSelectRow of popover
[[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" withObject:objectToPass];
In detail VC
- (void) didReceiveNotificationPassObject:(NSNotification*)notification
{
YourObjectClass *theObject = (YourObjectClass*)notification.object;
}
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didReceiveNotificationPassObject:) name:#"PassObject" object:nil];
}
Probably just a typo when entering the question but in the first line where you post the notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" withObject:objectToPass];
the method signature is wrong - it should be 'object:objectToPass' not 'withObject:objectToPass'. The line you have there will compile with a warning and crash at runtime.
Aside from that all the logic seems fine.
What is the problem you are facing? Does didReceiveNotificationPassObject: hit? If it doesn't, you could verify that viewDidLoad executes before didSelectRow.
Use [[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" object:objectToPass]; instead of [[NSNotificationCenter defaultCenter] postNotificationName:#"PassObject" withObject:objectToPass];
Also, don't forget to removeObserver in viewDidUnload.
HTH,
Akshay
A fast and easy solution to notify with multiple parameters is to call the notification it like this
[[NSNotificationCenter defaultCenter] postNotificationName:#"shareButton" object:#"camera"];
Where "camera" acts like your parameter. Then
- (void)shareButton:(id)sender
{
NSString *kindOf = [sender object];
if ([kindOf isEqualToString:#"camera"]) {
// Your code goes here
}
}