Not able to call UITabview from NSNotificationCenter in IOS - ios

I was able to implement the below mentioned library in my project.
Library used:: https://github.com/rolandleth/LTHPasscodeViewController
After entering the pin-code and after verifying that it is correct, i am not able to switch to tab-bar activity after the pin-code entry directly but if i use an NSNotification in between i am able to transfer control.
My code:
- (void) receiveTestNotification:(NSNotification *) notification
{
if ([[notification name] isEqualToString:#"TestNotification"])
NSLog (#"Successfully received the test notification!");
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
mainTabViewController *objSec=[storyboard instantiateViewControllerWithIdentifier:#"passID"];
[self.navigationController pushViewController:objSec animated:YES];
After putting an NSLog also i am getting the Log output but the tab-view doesn't come.
Is there a way to call the tab-view directly after pin-entry.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveTestNotification:)
name:#"TestNotification"
object:nil];
Tabview done using StoryBoard.

I think it happens because callback method from this library are performed in background thread, try to wrap you code with dispatching on main thread, it should help:
dispatch_async(dispatch_get_main_queue(), ^{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
mainTabViewController *objSec=[storyboard instantiateViewControllerWithIdentifier:#"passID"];
[self.navigationController pushViewController:objSec animated:YES];
}];

Related

iOS: Reinitialize the the app from top view controller if it is coming from background

I want to reinitialize my app from top view controller problematically. I want my app reload the views from start.
I have tried this in applicationWillEnterForeground method:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
ActivityController *destViewController = (ActivityController *)[storyboard instantiateViewControllerWithIdentifier:#"ActivityView"];
[self.navigationController pushViewController:destViewController animated:YES];
But it doesn't work.
If you don't want your app to be running in the background, you can set UIApplicationExitsOnSuspend to true in your app's Info.plist
applicationDidEnterBackground and applicationWillEnterForeground,
[[NSNotificationCenter defaultCenter] postNotificationName:#"popToRoot" object:nil];
and in your rootViewController's viewDidLoad (that always appears on app launch) add this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(popToRootViewControllerAnimated) name:#"popToRoot" object:nil];
Then create a method in your rootViewController:
- (void)popToRootViewControllerAnimated
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
You should use [self.navigationController popToViewController:ActivityController animated:NO]; instead of popToRoot.
Refer this answer for more details.

iOS: Display notification message when application opens

I have a textview and an imageview in my app so i can display the notification text and the image that i want to show. i receive this image from a url that i send via the notification. When i send notifications to my application and the app isn't running, the textview and the imageview doesnt show the content, but when the app is running or when the app state is in background the content updates.
I suppose that i have to configure the didFinishLaunchingWithOptions function when the app starts in order to update the fields of the view controller.
how can i do that? and why the didReceiveRemoteNotification function doesnt update the view when the app starts and updates the view only in two states (active & background)?
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"New notification received!");
[self.window makeKeyAndVisible];
//Notification recieved & handle the aps
NSDictionary * notificationDict = [userInfo objectForKey:#"aps"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshView" object:notificationDict];
NSString * alertString = [notificationDict objectForKey:#"alert"];
NSString * serverUrl = [notificationDict objectForKey:#"acme"];
NSLog(#"Notification text is: %#", alertString);
[[NSUserDefaults standardUserDefaults] setObject: alertString forKey: #"alertMSG"];
[[NSUserDefaults standardUserDefaults] synchronize];
//handle the notification when the app is active, inactive or in background
if ( application.applicationState == UIApplicationStateActive )
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"viewController2"];
[self.window.rootViewController presentViewController:vc animated:YES completion:nil];
application.applicationIconBadgeNumber = 0;
}
else if(application.applicationState == UIApplicationStateInactive)
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"viewController2"];
[self.window.rootViewController presentViewController:vc animated:YES completion:nil];
application.applicationIconBadgeNumber = 0;
}
else //ApplicationState Background
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"viewController2"];
[self.window.rootViewController presentViewController:vc animated:YES completion:nil];
application.applicationIconBadgeNumber = 0;
}
}
EDIT:
I have configure the didFinishLaunchingWithOptions to starts my controller when the app is launched from a notification, but the content still doesn't update beside the fact that i have signed an observer between the view controller and the app delegate. what am i missing ?
here is the code :
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions{
if (launchOptions != nil)
{
NSDictionary * dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
[self handleRemoteNotification:dictionary];
}
}
}
-(void)handleRemoteNotification:(NSDictionary*)payload{
NSDictionary * notificationDict = [payload objectForKey:#"aps"]; //extract some information from payload
[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshView" object:notificationDict];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"viewController2"];
[self.window.rootViewController presentViewController:vc animated:YES completion:nil];
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;}
ViewController2.m:
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//Observer for remote notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refreshView:) name:#"refreshView" object: nil];
notifTextf.delegate = self;
}
//Update View when notification is received
-(void)refreshView:(NSNotification *) notification
{
// Do whatever you like to respond to text changes here.
NSLog(#"observer notification message text is: %#", [notification.object objectForKey:#"alert"]);
NSLog(#"observer notification message url is: %#", [notification.object objectForKey:#"acme"]);
[self.notifTextf setText: [notification.object objectForKey:#"alert"]];
//Download image from Url sended by notification and display it
NSString * imageurl = [notification.object objectForKey:#"acme"];
NSURL *url = [NSURL URLWithString:imageurl];
self.notifImg.image = [UIImage imageWithCIImage:[CIImage imageWithContentsOfURL:url]];
}
why the didReceiveRemoteNotification function doesnt update the view
when the app starts and updates the view only in two states (active &
background)?
If the app is not running when a push notification arrives, the system launches the app and provides the appropriate information in the launch options dictionary. The app does not call application:didReceiveRemoteNotification: method to handle that push notification. Instead, your implementation of the application:willFinishLaunchingWithOptions: or application:didFinishLaunchingWithOptions: method needs to get the push notification payload data and respond appropriately.
Implement the application:didReceiveRemoteNotification:fetchCompletionHandler: method instead whenever possible (iOS 7 and above).
Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls the application:didReceiveRemoteNotification:fetchCompletionHandler: method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode (to support this mode, include the UIBackgroundModes key with the remote-notification value in your app’s Info.plist file), the system launches your app (or wakes it from the suspended state) and puts it in the background state when a push notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
Continue reading...

NSNotification delay from class A to class B

My NSNotification is delayed.
In myVC, I have two buttons, buttonA and buttonB. Each one is linked to their respective pdfs, pdfA and pdfB. There is a button Push, which is pressed after A or B is pressed. Push brings the user to the RVC where there is a UIWebView.
I want it so that by pushing either A or B, the UIWebView will display the respective pdf file. To debug this, I set it so that instead of changing the pdf, it will display text using NSLog. However, it doesn't work until after go back to myVC from the RVC by pressing a different button.
in myVC.m file:
- (IBAction)open_pictures_A:(id)sender
{
//do some button alert popup action/whatever button does
RootViewController *dataObject = [RootViewController new];
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:dataObject
forKey:#"buttonA"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification"
object:nil
userInfo:userInfo];
}
And there is one like that for buttonB, but forKey would be "buttonB"
in the viewDidLoad for myVC.m I have
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification"
object:nil];
in my RVC,
RVC.h I have
#property (nonatomic, strong) NSString *property1;
And in the RVC.m I have
- (void)viewDidLoad
{
// other stuff
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(eventListenerDidReceiveNotification:)
name:#"MyNotification"
object:nil];
}
- (void)eventListenerDidReceiveNotification:(NSNotification *)notif
{
if ([[notif name] isEqualToString:#"MyNotification"])
{
NSLog(#"Successfully received the notification from buttonB!");
NSDictionary *userInfo = notif.userInfo;
RootViewController *dataObject = [userInfo objectForKey:#"buttonB"];
// Your response to the notification should be placed here
NSLog(#"dataObject.property1 -> %#", dataObject.property1);
}
}
However, the log entry only shows up when I press a button to exit out of the RVC back to myVC
Here is the code I use to go from mVC to RVC
-(IBAction)goToRVC{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
RootViewController *RVC = [storyboard instantiateViewControllerWithIdentifier:#"Root"];
[UIApplication sharedApplication].delegate.window.RootViewController = RVC;
}
Then from RVC to myVC
-(IBAction)backtomyVC{
[[[UIApplication sharedApplication] delegate] performSelector:#selector(myVC)];
[self disconnect];
}
Why is my notification action being delayed?
It's not because of delay.
When you press your button A or B you create new RVC object and you post the notification however you don't present/push RVC view controller (you just initialise it) so the RVC hasn't fired viewDidLoad method and it hasn't register itself as an observer.
After that you call goToRVC method where you create RVC object and you add it to the view hierarchy so the viewDidLoad method is call and the object register itself as an observer.
When you go back to mVC the RVC is not deallocated yet so it receive the notification and you can see the log.
Hope it's clear.

Pushing iOS UIViewController from NSObject class

I have the following code within my AppDelegate. It is used during checks for In App Purchase expiry, and if a subscription is expiring, will present a popup for the user to choose to renew, and if they do, it will push the view controller for the In App Purchases onto the stack.
I would like to shift the code out of AppDelegate, and into its own NSObject class (just for tidiness). However, how do I call push the View Controller from another class?
self.window.rootViewController doesn't exist on the NSObject class, so of course won't function.
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UICollectionViewController *ivc = (UICollectionViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"IAPViewController"];
[navigationController pushViewController:ivc animated:YES];
In your NSObject class, when you want to push a vc, post a notification via NSNotificationCenter:
[[NSNotificationCenter defaultCenter] postNotificationWithName:#"PushMyViewControllerNote" object:nil];
And in AppDelegate.m register observer:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//...
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handlePushVCNotification:)
name:#"PushMyViewControllerNote"
object:nil];
//...
return YES;
}
//...
- (void)handlePushVCNotification:(NSNotification *)note
{
// First you must find currently visible view controller
// for how to do it, find it yourself :)
// but you can check https://gist.github.com/snikch/3661188
UIViewController *visibleVC = [self findVisibleVC];
UINavigationController *nc = visibleVC.navigationController;
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UICollectionViewController *ivc = (UICollectionViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"IAPViewController"];
[nc pushViewController:ivc animated:YES];
}
What you should do is create a separate class that inherits from NSObject. Call it something like AppPurchase. Then, import your AppPurchase class into your app delegate. As for pushing the view controller, that code should be separate from your AppPurchase class.
The AppPurchase class is part of your Model, and should not be responsible for pushing view controllers around. If data changes in your AppPurchase instance, then the controller can take some action and alter your View.
You should look into learning more about MVC or Model-View-Controller.

open a viewcontroller from storyboard when receive apple pushnotification

i am developing a app that has a storyboard with 3 view controllers and app in push notification enabled. and when i receive a push notification and when i tap on notification alert it should open a second view controller from my storyboard let me show my code.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"pushNotification" object:nil userInfo:userInfo];
}
and then storyboard loads which is actually my first view controller which also have a button in it to second view controller and that is the controller i want to load. and here is the code in my first view controller.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(pushNotificationReceived) name:#"pushNotification" object:nil];
}
-(void)pushNotificationReceived{
NSString * storyboardName = #"DealerMainStoryboard";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"DealerBuyRequests"];
[self presentViewController:vc animated:YES completion:nil];
}
so when i receive notification with this code app crashes when i tap on notification.
You need to get some error log but check this.
UIViewController * vc =
[storyboard instantiateViewControllerWithIdentifier:#"DealerBuyRequests"];
I don't think you want to create a new UIViewController , unless you really named your controller "UIViewController".
So check again the class name of the View you want to present modally
DealerBuyRequestsViewController * vc =
[storyboard instantiateViewControllerWithIdentifier:#"DealerBuyRequests"];
Make sure the StoryBoard Id of this View controller matches DealerBuyRequests or you will get errors.

Resources