ios push notifications to a specific view controller - ios

My app receives remote push notifications and upon receiving them, i would like to take it to a specific view controller(pretty much all the time). I have seen code like this (on didReceiveRemoteNotification). I am using storyboard for my apps.
UIViewController *vc = self.window.rootViewController;
PushViewController *pvc = [vc.storyboard instantiateViewControllerWithIdentifier:#"someid"];
[vc presentViewController:pvc animated:YES completion:nil];
This seems straightforward enough. But will it have any impact on memory allocation, as it looks like every time a push notification arrives, we are instantiating a new view controller. Is this the best practice?

you can try something like:
PushViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"someid"];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:vc animated:YES completion:nil];
You dont need to allocate uiviewcontroller as rootview everytime unless you want to have a uiviewcontroller present your pushVC.
if you are doing this in app delegate, the get the storyboard reference by:
UIStoryboard *test=[UIStoryboard storyboardWithName:#"name" bundle:nil];
and then call
[test instantiateViewControllerWithIdentifier.....

The above code you have mentioned is fine. But the logic remains upto you on how to handle. If it is intended that you always want different VC's for your push notification, then it is fine.
Say if you get two push notification instantly where two VC's will be presented immediately. But you want just one screen for the Push then this will be in trouble.
If you want to have one pushViewController object then you can make it a global object and do a simple check like this
UIViewController *vc = self.window.rootViewController;
if(!pvc)
{
pvc = [vc.storyboard instantiateViewControllerWithIdentifier:#"someid"];
}
[vc updatePushViewControllerDependingOnPushNotificationObject:somePushObject];
[vc presentViewController:pvc animated:YES completion:nil];

Related

Is there a way to dismiss the current ViewController after presenting another?

After some time searching for an answer, I have to admit that i'm pretty confuse with this case.
At my job, I'm asked to do something really specific :
I have to present a UIViewController on a previous UIViewController, actually, the current ViewController dismiss itself before the second appear. That give the whole thing a funny animation that a ViewController goes down and another rise from the bottom after this. But... It's not really "pro" and, we're able to see the rootViewController behind the scene during the animation.
So, I have to precise that there is NO NavigationController, that would have made this a lot easier in my opinion, so I'm forced to do it with two UIViewController, and there is my actual code :
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"userViewController"];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:controller animated:YES completion:^{
[self dismissViewControllerAnimated:YES completion:nil];
}];
It is call right after a button is pressed, so there is no problem with the actual ViewController viewDidLoad or viewDidAppear I think.
But each time this code runs, I get the following error :
[1163:17641] Warning: Attempt to present <UserViewController: 0x7b0f0a00> on <EIHomeViewController: 0x7b0d2a00> whose view is not in the window hierarchy!
I don't really know how I could manage to keep a trace of the current UIViewController to dismiss it in the next ViewController viewDidAppear to be sure there will be no "blackout" on the screen.
Thank you for your help in advance!
Try this code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"userViewController"];
[self dismissViewControllerAnimated:NO completion:^{
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:controller animated:NO completion:nil];
}];

Calling an animation only once in ViewDidAppear even reloading the view

I am having a problem in an animation of a view.
Firstly, I made an animation within ViewDidLoad method. It works perfectly.
Then within the view, I need to call out another view from the storyboard by storyboard ID using the below method
UIStoryboard *story = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
myprofile *obj = [story instantiateViewControllerWithIdentifier:#"myprofile"];
[self presentViewController:obj animated:YES completion:nil];
This view is just use for preferences and setting. After the setting is done, I called
[self dismissViewControllerAnimated:YES completion:nil];
The problem came when it dismissed. It can go back into the viewDidload before, but the animation started again.
My question is, is there anyway I can skip the animation that I called in viewDidload when I dismiss my second view?
Many Thanks
You can use add/post local notification for this.Manage a bool variable with YES for a go animation and NO for no animation.
Add observer in the viewdidLoad before calling the animation.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(SettingsDone) name:#"AnimationDone" object:nil];
if (goAnimate){
UIStoryboard *story = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
myprofile *obj = [story instantiateViewControllerWithIdentifier:#"myprofile"];
[self presentViewController:obj animated:YES completion:nil];
}
-(void)SettingsDone{
goAnimate=NO;
}
You can post a local notification to parent class before dismissing the pop up view.
[NSNotificationCenter defaultCenter]postNotificationName:#"AnimationDone" object:nil userInfo:nil];
[self dismissViewControllerAnimated:YES completion:nil];
Maybe you can create a class which inherit of UIViewController with a attribute like var playing : Bool = true and change it before dismiss you view controller.
Since you re-create your controller each time before displaying it, you need to store a flag somewhere. Roughly speaking the quick hack would be to use dispatch_once on your animation. But you may decide to store a flag in parent controller and manually start animation from parent controller. There are really million ways to organize it.

Presentview(full screen) controller while dismissing View1 which is model view itself

I have an ipad app.
I am trying to open view 2 (kind of push view) full with entire screen. how normally do with push view or UIModalPresentationFullScreen. but my base view which is view 1 is also modal view.
so i was trying to open view 2 when view 1 get dismiss…
- (void) handleNewButton :(int)id
{
[self dismissViewControllerAnimated:YES
completion:^{
NewViewController *View2 = [NewViewController alloc] init];
View2.modalPresentationStyle = UIModalPresentationFullScreen;
View2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController: View2 animated:YES completion:nil];
}];
}
but my view 2 is not opening. i know i can not do push view. But is there any way to achieve it?.
When you do this dismissViewControllerAnimated the UIViewController (self in this case) is gone, in the sense that he is not on the screen anymore, if it has been released or not, that's another story. The reason for you to not be able to show the View2 (very poor name, it should at least ViewController2) is because you are trying to show it from a UIViewController that is not on the screen anymore.
So, what can you do?
The current self in the context of the handleNewButton method, in theory was presented by another UIViewController, that's from where you want to present your View2.
Probably the quickest way of implementing of what I said, would probably be with a notification described here. Although I would do it with a block, so when the self would be created, I would pass a dismissiCompletionBlock that would be called when that UIViewController was dismissed.
try to allocate NewViewController with nib name if you are not using storyboard,
[self dismissViewControllerAnimated:YES
completion:^{
NewViewController *n=[[NewViewController alloc]initWithNibName:#"NewViewController" bundle:nil];
View2.modalPresentationStyle = UIModalPresentationFullScreen;
View2.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController: View2 animated:YES completion:nil];
}];
or if you are using storyboard get NewViewController using identifier.

Dismiss UIViewController after presenting another one

I'm developing a single view iOS 5.0+ app and I'm going to navigate throw my ViewControllers this way:
SearchViewController* search =
[[SearchViewController alloc] initWithNibName:#"SearchViewController"
bundle:nil];
[self presentViewController:search
animated:NO
completion:nil];
My question is, if I'm opening SearchViewController from HomeViewController, is HomeViewController dismissed after SearchViewController is shown?
I have a lot of UIViewControllers and I don't know if all of them will be on memory while user is navigating between them.
If You want to Present Only one Viewcontroller you can try like,
SearchViewController* search =
[[SearchViewController alloc] initWithNibName:#"SearchViewController"
bundle:nil];
[self dismissViewControllerAnimated:NO completion:^{
[self presentViewController:search
animated:NO
completion:nil];
}];
When you present a ViewController from another ViewController, they never get released from memory. To release them from memory you need to explicitly dismiss them.
The method presentViewController:animated:completion: sets the
presentedViewController property to the specified view controller,
resizes that view controller’s view and then adds the view to the view
hierarchy.
So you see you are getting a stack of ViewControllers and adding a View on top of another.

How and where would you use instantiateViewControllerWithIdentifier

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
MenuScreenViewController *controller = (MenuScreenViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: #"<Controller ID>"];
Where exactly do i write this code if i have to make sure that the current view is instantiated with the identifier? Which means if i write any code on this class it has to appear when this viewcontroller loads? Also how would i use it? I dont want to create an instance of the menuscreenviewcontroller. WHich means i have to say self but i used self.view and that doesnt work.
You need to push or present the view controller that you have created. You can not directly change views of the controllers by instantiating.
For example you need to use this code to trigger the transition (maybe a button action):
MenuScreenViewController* controller = (MenuScreenViewController*)[ourStoryBoard instantiateViewControllerWithIdentifier:#"<Controller ID>"];
controller.controlFlag = YES;
controller.controlFlag2 = NO; // Just examples
//These flags will be set before the viewDidLoad of MenuScreenViewController
//Therefore any code you write before pushing or presenting the view will be present after
[self.navigationController pushViewController:controller animated:YES];
// or [self presentViewController:controller animated:YES];
As per Uğur Kumru's answer, with a small edit: if you are not using a Navigation Controller, and you are developing against iOS 5.0+ you will need to use:
MenuScreenViewController* controller = (MenuScreenViewController*)[ourStoryBoard instantiateViewControllerWithIdentifier:#"<Controller ID>"];
[self presentViewController:controller animated:YES completion:nil];
If you omit the completion:nil you will face errors

Resources