I'm writing an application that checks a device's orientation, and because of that, I have the following code block:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
which in turn, calls the following method:
- (void) orientationChanged:(NSNotification *)note {
...
}
What I would like to do is call the above method separately from the initial code block that I posted from a separate section altogether. Is this possible, and if so, how?
What I usually do in this type of situation is pass nil as the argument:
[self orientationChanged:nil];
This depends on how critical the notification itself is to the implementation of the method. You may have to construct a notification with the appropriate information in it:
NSNotification *n = [NSNotification notificationWithName:#"someName" object:someObject];
[self orientationChanged:n];
However, I have come to view this type of need as a code smell, what I try to do instead is extract the work the notification handler performs into a separate method and call that one directly, e.g.:
- (void)handleOrientationChangeForDevice:(UIDevice *)d {
// do something here
}
- (void)orientationChanged:(NSNotification *)n {
[self handleOrientationChangeForDevice:n.object];
}
Then, in the calling code, you could do something like:
[self handleOrientationChangeForDevice:[UIDevice currentDevice]];
If you need the device's orientation without waiting for the Notification, you can just get it this way:
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
You can call it by passing nil parameter or whatever object of type NSNotification you want to pass like
To call it in .m of same class-
[self orientationChanged:nil];
To call from another class-
[controller orientationChanged:nil]; //Declare method in .h first
Related
App delegate:
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter] postNotificationName:APP_REFRESH_NOTIFICATION object:nil];
}
In my view controller:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doStuff) postNotificationName:APP_REFRESH_NOTIFICATION object:self];
}
- (void)doStuff never gets called. Why?
I assume that you've typed your question incorrectly and you'd meant to write addObserver:selector:name:object:, instead of addObserver:selector: postNotificationName:object: (such method doesn't exist).
In the documentation of - (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender
we can read:
notificationSender
The object whose notifications the observer wants
to receive; that is, only notifications sent by this sender are
delivered to the observer. If you pass nil, the notification center
doesn’t use a notification’s sender to decide whether to deliver it to
the observer.
So in your case, as you're passing object:nil in postNotificationName:object:, you also have to set object:nil in addObserver:selector:name:object:.
According to the documentation you also should replace the method doStuff with:
- (void)doStuff:(NSNotification *)notification
and use #selector(doStuff:) in addObserver:selector:name:object:.
You're passing self as the object parameter to addObserver:selector:name:object:, but doStuff doesn't accept any parameters, so the method call fails (silently). Your viewDidLoad should look like this:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(doStuff)
name:APP_REFRESH_NOTIFICATION
object:nil];
}
You're app delegate is posting a notification when the app becomes active, but your view controller isn't subscribing to that until its view gets loaded. If your app delegate is creating your view controller and loading it (which is probable) then your controller doesn't even exist at the time the notification is posted, which is why it isn't receiving it. If you use a storyboard, and that controller is the entry point in the storyboard, AND you use the info.plist for your app to set that storyboard as the main interface, then it will have already instantiated the controller and loaded its view by the time -applicationDidBecomeActive: is called, solving your problem.
I have two methods in viewDidLoad of the app and I want that if the notification method is called then the other method should not be called.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(actionNotificationDataA:)
name:#"reloadDataActivity"
object:nil];
Below is the other method. I want that if the notification method is not called, then this method should be called:
[NSThread detachNewThreadSelector:#selector(allData:) toTarget:self withObject:nil];
Otherwise, this method shouldn't be called.
First one will get called only when post that notification somewhere. But the second will detach the new thread suddenly when the code runs. That may create a problem look at it.
For an idea to your requirement:
Keep a BOOL with default to NO.
Then in the both methods check if the boolValue is NO, then run the code only if boolValue is NO and change the boolValue to YES.
Put BOOL isNotifCall; in your .h file.
In starting of viewDidLoad Method, give NO to isNotifCall, such like,
- (void)viewDidLoad
{
[super viewDidLoad];
isNotifCall = NO;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(actionNotificationDataA:)
name:#"reloadDataActivity"
object:nil];
[NSThread detachNewThreadSelector:#selector(allData:) toTarget:self withObject:nil];
}
Method of your NSThread (I don't know about parameter so i take id)
-(void)actionNotificationDataA:(id)Sender
{
isNotifCall = YES;
.
.
.
/// your Stuuf;
}
Method of your notification (I don't know about parameter so i take id)
-(void) allData:(id)Sender
{
if(!isNotifCall)
{
/// your allData method's Stuuf;
}
}
I am using push notifications in my code and whenever a notification comes, I want to update the value of a label in another ViewController.
My code in AppDelegate is:
- (void)addMessageFromRemoteNotification:(NSDictionary*)userInfo updateUI:(BOOL)updateUI
{
NSLog(#"Notification arrived");
//[mydeals setCode1_id:mydeals.code1_id withString:#"123456"];
mydeals=[[MyDealsViewController alloc]init];
NSDictionary* codeDetails=[[NSDictionary alloc] initWithObjectsAndKeys:#"123456",#"Code_id", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"CodeArrived" object:self userInfo:codeDetails];
}
then in my other view controller I have this code:
#implementation MyDealsViewController
-(id) init
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveCode:)
name:#"CodeArrived"
object:nil];
return self;
}
-(void) receiveCode:(NSNotification*)notification
{
NSLog(#"received Code: %#",notification.userInfo);
self.code1_id.text=[NSString stringWithFormat:#"%#",[[notification userInfo] valueForKey:#"Code_id"]];
}
the log is printed correctly but when I manually go into that screen I see the default value, like the label is not updated at all. What should I do?
You have to make sure that when you "manually go" to MyDealsViewController, whatever how you do it, it got to be the same instance of MyDealsViewController wich has been called receiveCode. Otherwise it's going to init with it's default values.
You might also try calling [self.code1_id setNeedsLayout];
Context
We were developing an ios app that can uses opencv and had to change our viewcontrollers to .mm
opencv related functions in the .mm won't execute code that involves changes in the ui.
GazeTracker is an NSObject that tells the state of the user's gaze and it works fine
we thought of using observers so that we'll use a selector in the viewController called stateChanged which will execute whenever the state in gazeTracker is changed.
"stateChanged" is never called. We initially thought it was just gazeTracker so we replaced it with "self" (meaning the viewController) and it still won't work.
Our understanding of the "observer" is that when a value in an object is changed, the selector is called. However we don't know the purpose of "object" in "addObserver:selector:name:object".
the original code
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:gazeTracker.state
selector:#selector(stateChanged)
name:#"stateChanged"
object:nil];
}
-(void)stateChanged{
NSLog(#"some value in gaze tracker has changed");
}
with "self"
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(stateChanged)
name:#"stateChanged"
object:nil];
}
-(void)stateChanged{
NSLog(#"some value in gaze tracker has changed");
}
I want to show a full page image Ad every time a UIViewController is shown.
I think I have to call the method inside a viewDidAppear or ViewWillAppear, but they are being called once.
- (void) viewDidAppear:(BOOL)animated{
[self showAds];
}
- (void) showAds{
//Do Something
}
What should I do to call a method every time a uiviewcontroller is shown( even if its already created)?
ViewWillAppear will be called every time a UIViewController is shown,but won't be called when the app is back to foreground.
you can use Notification to achieve your goal by following code,
This scenario is specially when your app is in background and user press HOME button to active it.
Register for Notifcation when your application enterForground in viewDidLoad only.
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(handleEnteredBackground)
name: UIApplicationDidBecomeActiveNotification
object: nil];
write a method to invoke when application enterForground
-(void)handleEnteredBackground
{
NSLog(#"%s",__FUNCTION__);
// Your stuff here
}
Dont forget to Remove Observer in viewDidUnload method
[[NSNotificationCenter defaultCenter] removeObserver:self];
Post New Notification everytime your application enterForground
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil];
}
ViewWillAppear should be called every time. Use:
- (void) viewWillAppear:(BOOL)animated{
[self showAds];
}