I have an app that has a navigation controller in a tabbar controller. The root for the navigation controller is a table view controller. The table view has a segue to an image view. I want to update the badge value on a tab from the image view controller. From the tabbar controller, this works fine:
UIViewController *viewController = [self.tabBarController.viewControllers objectAtIndex:1];
viewController.tabBarItem.badgeValue = #"x";
But when I put the same code into the imageview controller, it doesn't work. When I check the value of 'viewController' after it executes, the value is nil. Same for self.tabBarController. For some reason the image view controller can't see its tabbarcontroller.
You should be able to access the tabBarController with self.navigationController.tabBarController. So your code needs to be:
UIViewController *viewController = [self.navigationController.tabBarController.viewControllers objectAtIndex:1];
viewController.tabBarItem.badgeValue = #"x";
so there are many ways to do this but the best way would be subcscribe to an NSNotification and then from your image view or wherever, make that notification so it would look something like.
[[NSNotificationCenter defaultCenter]
addObserver:objectToListen
selector:#selector(methodToRun:)
name:#"NotificationName"
object:nil];
And then in you deeper items such as the imageview or whatever you post it like this
[[NSNotificationCenter defaultCenter] postNotificationName:#"NotificationName" object:nil userInfo:dictionaryWithValuesForMethodToUse to use];
And then you get the information from the userInfo like so in you method that changes the badge value
- (void)methodToRun:(NSNotification *)notification
{
NSDictionary *dictionary = [notification userInfo];
}
Related
As shown in the picture above, I have two view controllers, one of which is within a navigation controller. When a button is pressed in controller A, controller B is presented through the navigation controller and is displayed modally. Is it possible for me to pass data from controller B back to controller A when the dismiss function is called on B?
You can use delegation pattern or callbacks to do this
If you are using storyboards and navigating using segues, then an unwind segue will do this for you. Here is a simple tutorial that should help:
https://www.andrewcbancroft.com/2015/12/18/working-with-unwind-segues-programmatically-in-swift/
This stack overflow answer has much more detailed and valuable information on this topic
Passing Data between View Controllers
You can pass through NSNotificationCentre .
First you need to add Notification Observer and its selector in ViewControllerA as below :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveTestNotification:) name:#"notificationName"
object:nil];
-(void) receiveTestNotification:(NSNotification*)notification
{
NSDictionary* userInfo = notification.userInfo;
NSLog (#"%#",userInfo);
}
Now in ViewController B you need to post notification as below :
NSDictionary* userInfo = your data ;
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:#"notificationName" object:self userInfo:userInfo];
Hello I am using Page menu in application and i want to push from didSelectRowAtIndexPath in next view in one view which is involed in page menu
i know all way which we use for push and model.if i am using model with custom navigation bar then page menu hide on dismiss model.
Assumed hierarchy:
UINavigation Controller -- UIViewController -- UIPageController
UIPageController (with 2 UIViewController) -- UITableViewController-1 and UITableViewController-2
On didSelectRowAtIndexPath method
UIPageController -- UITableViewController-1 //Selected any one row
Then just push the next view controller onto the current UITableViewController.
Note - Both controller in UIPageController maintain separate life cycle that is independent from each other.
One can not push the viewcontroller in pageView , PageviewController don't have navigation controller .
Solution :
There are two ways to make this possible suggested by Nitin Gohel
set notification for event and Retrieve the notification on main Controller
You can send the information in Notification required in another viewController.
NSDictionary* userInfo = #{#"abc": #"aaa"};
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:#"One" object:self userInfo:userInfo];
In MainViewController just set the onserver for that notification in viewDidLoad method
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(OneNoti:) name:#"One" object:nil];
}
And perform push from MainViewController:
-(void) OneNoti:(NSNotification*)notification
{
NSDictionary* userInfo = notification.userInfo;
NSNumber* total = (NSNumber*)userInfo[#"total"];
NSLog (#"Successfully received test notification! %i", total.intValue);
NSLog(#"%#",notification.userInfo);
[self performSegueWithIdentifier:#"1_" sender:nil];
}
Set the delegate methods in MainView Controller and call the methods while performing action from page view and push from that Action .
Same like above way .
Scenario:
I have a calendar control as a UIview and I want that when I click on date button of the view I want to navigate to some other UIview controller but when I use:
HomeView *scrhome=[[HomeView alloc]init];
[self presentViewController:scrhome animated:YES completion:nil];
It gives an error:
HomeView is not in memory stack
Thanks in advance.
As schrome is UIView not a view controller,it can not be passed an argument as required type is uiviewcontroller. What you can do is use this uiview inside a controller and that viewcontroller's object can be passed as an argument.
you can use observer Pattern
see you can create an observer using NSNotificationCenter:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notify) name:#"Event" object:nil]; //1
put this in your view controller.
and a selector in view controller like:
-(void)notify
{
//2
HomeView *scrhome=[[HomeView alloc]init];
[self presentViewController:scrhome animated:YES completion:nil];
}
and in your view write under a condition where you want to throw an event:
[[NSNotificationCenter defaultCenter] postNotificationName:#"Event" object:nil]; //3
and you are ready to go.
you may use object:yourobject in place of nil # //1
and
id=sender;
if you want to get some attributes to work on.
it works fine for me.
presentViewController: expects to have view controller as a parameter, you are passing a view here. Have a controller for your view and pass it in presentViewController: animated:
I have a viewController I've built in storyboard. I also have a NSObject Subclass which acts as my model, which sends and listens for API requests and responses. When a method fires in my model, I want to present a modal View of my viewController from whatever view happens to be visible at the time.
An example would be if my API hears "show this view" I want to show viewController regardless of what view is being shown.
Conceptually, how does one do this?
EDIT: I don't know which view controller will be showing when I want to present my modal viewController. Also, I need to pass params from my model to the modalVC when it's presented.
I would send a notification from the model telling "someone" that some view needs be displayed.
NSDictionary *userInfo = #{ #"TheViewKey": viewToDisplay];
[[NSNoticationCenter defaultCenter] postNotificationName:#"NotificationThatThisViewNeedsToBeDisplayed" object:self userInfo:userInfo];
And then on the delegate (or the active view controller) would register to this notification and handle the display.
// self is the delegate and/or the view controller that will receive the notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleViewToDisplay:) name:#"NotificationThatThisViewNeedsToBeDisplayed" object:nil];
If you put in the view controller remember to remove self from the observers when the view is not visible:
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"NotificationThatThisViewNeedsToBeDisplayed"];
This way your model is decoupled from the presentation.
You have the current viewController (any viewController subclass) present the new view using:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
EDIT: To find the top view controller, you ask the UITabBarController for the selectedViewController (if you use a tabBarController) to get the 'seed', or start with the window.rootViewController.
Once you are past any tabBarControllers, then you should only have UIViewController subclasses and UINavigationControllers. You can use a loop like this:
- (UIViewController *)frontmostController:(UIViewController *)seed
{
UIViewController *ret;
if([seed isKindOfClass:[UINavigationController class]]) {
ret = [(UINavigationController *)seed topViewController];
} else
if([seed isKindOfClass:[UIViewController class]]) {
ret = seed.presentedViewController;
}
return ret ? [self frontmostController:ret] : seed;
}
I have created a Tab Bar Application using Xcode that as two views.
The secound view is a UITableViewController.
What I am struggling to do is send data to this view, when the second tab is pressed. I have delegated the Tab Bar to my AppDelegate class and implemented this function:
-(void)tabBarController:(UITabBarController*)tabBarController didSelectViewController:(UIViewController*)viewController
{
// Override point for customization after application launch.
statisticsViewController* assignmentListcont = [statisticsViewController alloc];
NSManagedObjectContext* context = [self managedObjectContext];
assignmentListcont.managedObjectContext = context;
[assignmentListcont release];
}
The second view is displaying fine but the data hasn't been passed. I imagine its because I haven't programmed the second views transition but I'm unsure of how to do this if I already have a .xib file doing it for me? Is there some way to just pass the data without problems or even retrieve the data once inside the view?
You could use notifications.
In the view that you want to receive the data, put this in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(yourSelector:)
name:#"addedData"
object:nil];
Then implement the method that receives that data:
- (void)yourSelector:(NSNotification *)notification {
Foo *foo;
foo = [notification object];
//do something else
}
Now in the class where the data is originated from, you post a notification that new data was created. Also, you pass along the data that you want to have the other method receive.
[[NSNotificationCenter defaultCenter] postNotificationName:#"addedData"
object:foo];
I've done this to send a value from one view controller to another, hope it helps
UITabBarViewController *var = [self.storyboard instantiateViewControllerWithIdentifier:#"name"]; //I select the UITabBarController
otherViewController *var2 = [var.childViewControllers objectAtIndex:0]; //I Select the first ViewController from that UITabBarController
var2.variable = #"value";
[self.navigationController pushViewController:var animated:YES];