How to check if notification is called then do not call method - ios

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;
}
}

Related

Notification fired twice even tho adding observer only once

I have two class which uses NSNotification to communicate with each other.
Currently, i have an issue with notification being fired twice, i've double/triple/even more checked that observer is not added more then 1 time, notification not being posted twice, did global search on my project for same notification.
My code is like below
Added Notification Observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:notification_deleteMediaFromGallery object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationReceiver:) name:notification_deleteMediaFromGallery object:nil];
Notification Receiver
- (void)notificationReceiver:(NSNotification*)notification {
if ([notification.name isEqualToString:notification_deleteMediaFromGallery]) {
if ([[notification.userInfo objectForKey:#"kind"] integerValue]==GalleryKindPhoto) {
//My statements
}
else if ([[notification.userInfo objectForKey:#"kind"] integerValue]==GalleryKindVideo) {
//My statements
}
}
}
Post Notification
dispatch_async(dispatch_get_main_queue(), ^{
[_browser reloadData];
[[NSNotificationCenter defaultCenter] postNotificationName:notification_deleteMediaFromGallery object:nil userInfo:#{#"index":#(_browser.currentIndex), #"kind":#(self.kind), #"function":[NSString stringWithFormat:#"%s",__PRETTY_FUNCTION__]}];
});
I have also tried this solution by EmptyStack but not get it to work.
I'll be very thankful to you if you could help me solve this issue.
Thanks.
Edit
NOTE
I've added observer in my viewdidload, and cant add/remove observer from viewwillappera/viewwillappear or viewdidappear/viewdiddisappear because the next viewcontroller which will be pushed on current viewcontroller will post notifications
I think you need to write dealloc method in your view controller. And remove All Notification observer in dealloc method,
- (void)dealloc
{
// Deregister observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:notification_deleteMediaFromGallery object:nil];
}
Hi please make sure your method is not calling two time from where you are firing notification.
& please add your notification observer in viewWillDisappear method.

Object parameter in method postNotification of NSNotificationCenter

In my iOS application, I am posting a NSNotification and catching it in one of my UIView in main thread. I want to pass extra information along with the notification. I was using userInfo dictionary of NSNotification for that.
[[NSNotificationCenter defaultCenter] postNotificationName:#"NotifyValueComputedFromJS" object:self userInfo:#{#"notificationKey":key,#"notificationValue":value,#"notificationColor":color,#"notificationTimeStamp":time}];
key, value, color and time are local variables which contains the value I need to pass. In UIView I am adding observer for this notification and I am using notification.userInfo to get these data
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveNotification:) name:#"NotifyValueComputedFromJS" object:nil];
-(void)receiveNotification:(NSNotification *)notification
{
if ([notification.userInfo valueForKey:#"notificationKey"]!=nil && [[notification.userInfo valueForKey:#"notificationKey"] isEqualToString:self.notificationKey] && [notification.userInfo valueForKey:#"notificationValue"]!=nil) {
[self updateLabelWithValue:[notification.userInfo valueForKey:#"notificationValue"]];
}
}
The frequency in which this notification is posted is 4 times in one second. I am doing some animations also in main thread. The problem I am facing here is my UI is lagging. UI will respond to scroll events or touch events with huge delay(I have faced a delay of even 1 to 2 seconds). After some research I came to know that NSDictionary is bulky and will cause lag if used in main thread. Is there any other way I can pass my data through NSNotification?
I have tried out another way. I have created a custom NSObject class to save the data I want and I am passing it as the object parameter of postNotification method.
[[NSNotificationCenter defaultCenter] postNotificationName:#"NotifyValueComputedFromJS" object:customDataObject userInfo:nil];
Here customDataObject is an instance of my custom NSObject class. I know the parameter is meant to be the sender of notification(usually it will be self). Is it a wrong approach if I am sending a custom object as parameter?
As BobDave mentioned, the key is to send the notification on some thread other than the main UI thread. This can be accomplished with dispatch_async, or with a queue.
The typical pattern for this behavior is sender:
-(void)sendDataToObserver {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"NotifyValueComputedFromJS" object:customDataObject userInfo:userInfo:#{#"notificationKey":key,#"notificationValue":value,#"notificationColor":color,#"notificationTimeStamp":time}];
});
}
And receiver (NOTE: weak self because retain cycles):
-(void)addObserver {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveNotification:) name:#"NotifyValueComputedFromJS" object:nil];
}
-(void)receiveNotification:(NSNotification *)notification {
if ([notification.userInfo valueForKey:#"notificationKey"]!=nil && [[notification.userInfo valueForKey:#"notificationKey"] isEqualToString:self.notificationKey] && [notification.userInfo valueForKey:#"notificationValue"]!=nil) {
__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf updateLabelWithValue:[notification.userInfo valueForKey:#"notificationValue"]];
});
}
}
Maybe you could use - addObserverForName:object:queue:usingBlock:
and use a non-main queue to execute the block in order to reduce the lag. Also, shouldn't the observer be added in a UIViewController, not a UIView?

Save data from textField into a file when the application has closed or terminated

In my application has a view controller named "Home" with a textField.
I read about applicationDidEnterBackground and applicationWillTerminate methods in the AppDelegate file.
I know how to create, save, read data from a file.
My question is, How I can get an NSString from the "Home" viewController (that there store the textField data) to the AppDelegate applicationDidEnterBackground method and do there all my things with that data?
You could use NSNotificationCenter to register for a notification in your view controller that fires off whenever you enter applicationDidEnterBackground or applicationWillTerminate.
So in either of those methods you put something like
[[NSNotificationCenter defaultCenter] postNotificationName:#"someDescriptiveName" object:self userInfo:#{#"key" : #"value"}];
userInfo expects an NSDicitonary and you can pass it any type of object in there, in your case you dont need to pass anything from here back to your viewcontroller, your just using it as a means to let your view controller know the app is closing.
In your view controller you would register for that notification with something like this
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(methodToCall:) name:#"someDescriptiveName" object:nil];
Then whenever your appDelegate post that notification, your view controller which is registered to listen for it would fire off "methodToCall" which can be a method you right to do anything and it takes in an nsnotification which then lets you access the nsdicitonary its carrying.
- (void)methodToCall:(NSNotification *)notif{
NSLog(#"methodToCall fired with data %#",[[notif userInfo]valueForKey:#"key"]);}
You can do this with the help of this inside your controller:
-(id)init
{
if((self = [super init]))
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
}
return self;
}
-(void)appDidEnterBackground:(NSNotification *)note {
NSLog(#"appDidEnterBackground");
}
you can also use applicationWillTerminate in place of UIApplicationDidEnterBackgroundNotification

Call a method every time a UIViewController is shown

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];
}

Need help independently calling method: - (void) orientationChanged:(NSNotification *)note in iOS

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

Resources