New ways to transfer data between view controllers - ios

I have a problem with transferring data between UIViewController and I don't find answers in former questions.
Situation : I have a first viewController ('CalViewController') which allows users to input data. Then I calculate with those datas a number (named 'calories' for example). The next views are two UIViewController (DrinksViewController & FoodViewController)displayed in a TabBarControllerand I need value of 'calories'.
What I've tried :
-prepareForSegue method : It doesn't work because segues (symbol in storyboard is a link between two points) in a TabBarControllerare not as others (symbol in storyboard is arrow through a door).
-'didSelectViewController' method : This method is not "activated" to display the first view of a TabBarController. So I succeed to transfer Calories to my second ViewController in the TabBarController (ie FoodViewController) but not to my first viewController in the TabBarController (ie DrinksViewController).
-call the "original" value : Here what I've done in CalViewController (after imported DrinksViewController.h)
DrinksViewController *dvc = [[DrinksViewController alloc] init];
dvc.caloriesImported = 456;
I don't know why this third way is not working.
Problem : My value of Caloriesis not transferred from CalViewController to DrinksViewControlller. Any ideas ?

If I understand your problem correctly, the following should work in the first
view controller CalViewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"yourSegueToTabBarIdentifier"]) {
UITabBarController *tbc = [segue destinationViewController];
DrinksViewController *dvc = tbc.viewControllers[0];
dvc.caloriesImported = 456;
FoodViewController *fvc = tbc.viewControllers[1];
fvc.someProperty = someValue;
}
}
Note that
DrinksViewController *dvc = [[DrinksViewController alloc] init];
dvc.caloriesImported = 456;
cannot work because it allocates a new instance of DrinksViewController that
is completely unrelated to the instance used by the tab bar controller.

You need to get the instances that are already in the tab bar controller. You do that with self.tabBarController.viewControllers[n], where n would be 0,1, or 2 depending on which controller you're trying to access.

Related

How can i get button title on another view controller performing segue?

1) I am having an 2 view controller on 1st view controller having buttons as
a) Local and b) International
And I am using segment control on another view in which it has 2 bar Local and International
Now when i perform the segue i need to get the titles or some data so i can identify that which bar should be displayed first the local one or international.
And simply performing the segue doesn't gets the data passed on button event.
So how can i pass 2 different data on two different buttons by performing the segue ?
If the segue is connected to your button, then it will be the sender in prepareForSegue.so write this in prepareForSegue.
NextViewController *vc = segue.destinationViewController;
UIButton *dayButton = (UIButton*)sender
vc.titlestr = sender.titleLabel.text;
You can pass parameters to you view controllers inside prepareForSegue as follow example:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier]isEqualToString:#"mysegueidentifier"]){
NSDictionary *info = [[NSDictionary alloc]initWithObjectsAndKeys:
#"comment", #"type",
#"myId", #"elementId",
nil];
NextViewController *vc = segue.destinationViewController;
[vc setSegueInfo:info];
}
}
NextViewController must have a variable called segueInfo ([vc setSegueInfo:info];)
#property NSDictionary *segueInfo;

[UITabBarController setSports:]: unrecognized selector sent to instance 0x7b80e2b0

I’m building an iOS app. I want pass array value from one view controller to another through segue.
While doing this i’m getting an error:
[UITabBarController setSports:]: unrecognized selector sent to
instance 0x7b80e2b0.
here is my code:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"sportsSelection"]) {
Play *play=[segue destinationViewController];
play.sports=selectedSports;//error break point is here.
//sports and selected sports are NSMutableArray
}
}
To make the situation a bit clearer, you are getting the error because you are trying to call a method (setSports:) on a class that does not implement this method, this is exactly what the error message tells you:
[UITabBarController setSports:]: unrecognized selector sent to
instance 0x7b80e2b0.
Your segue apparently has a UITabBarController as destination, so it's clear that it does not know about the method setSports:, since this one is actually implemented in your custom view controller (apparently called Play?!).
Then, as Eike pointed out in his answer, you need to get Play from the UITabBarController which it is embedded in. That's why he suggested to use: Play* p = ((UITabBarController*)segue.destinationViewController).viewControllers[0];, it means that you should get the view controller at index 0 from your UITabBarController.
According to your comment, the view controller at index 0 is a UINavigationController, which (naturally) also does not respond to setSports:, because just like UITabBarController it is a class provided by Apple and doesn't know about this method.
Now, you need to find out where in this UITabBarController your custom view controller Play is located. Either it is a direct part of UITabBarController and you can find it by using Eike's approach and just modify the index from 0 to n (where n is the number of view controllers that the UITabBarController has hold of), or another option is that it is embedded in the UINavigationController that you received at index 0, so in that case you'd have to access the UINavigationController's view controller stack (e.g. the array property viewControllers or just the one that is currently on top of the stack using topViewController).
Edit: I want to give you some extra information about what's going on in your code, especially related to Eike's answer:
From the information that you gave us in your question and in the commment to Eike's solution, we can assume the following code to be correct:
if ([[segue identifier] isEqualToString:#"sportsSelection"]) {
UITabBarController *tabBarController = [segue destinationViewController]; // the destination of the segue is your `UITabBarController`
UINavigationController *navigationController = tabBarController.viewControllers[0]; // gets the first of the view controllers contained in your UITabBarController
NSLog(#"view controllers in navigation controller: %#; top view controller: %#", navigationController.viewControllers, navigationController.topViewController); // print all view controllers managed by navigationController
}
EDIT 2: From your comment I can now assume the following code to be correct:
if ([[segue identifier] isEqualToString:#"sportsSelection"]) {
UITabBarController *tabBarController = [segue destinationViewController]; // the destination of the segue is your `UITabBarController`
UINavigationController *navigationController = tabBarController.viewControllers[0]; // gets the first of the view controllers contained in your UITabBarController
Play *controller = (Play *)[[navigationController viewControllers] objectAtIndex:0];
controller.sports=selectedSports;
play.sports = selectedSports;
}
You need to setSports: to your view controller not the UITabBarController.
Play* p = ((UITabBarController*)segue.destinationViewController).viewControllers[0];
p.sports = selectedSports;

Steps on how to push segue to tableviewcontroller

I am having issues displaying data in a tableview from a push segue. How do you make data appear in the tableview from the push segue? Do I need to implement a delegate/protocol? What method would I add my logic to display the rows in the TableViewController from the push segue. I able to navigate to the tableview and back to the button sort view controllers.
Can someone show me the process similar how I wrote My Logic? I am stuck on step 4. If you have a easier way to execute please let me know.
Controllers I am trying to coordinate.
"EventFeedController.m " TableViewController executed from Tab Bar Controller. This shows the events.
" ButtonSort.m " to push segue to EventFeedController.m
AppDelegate.m has array.
My Logic...
In the storyboard.
Control drag from UIButton in ButtonSort directly to EventsFeedViewController (not to the navigationcontroller but directly to the view EventViewController itself. ). (Not sure if I should control drag to view controller or the navigation controller of EventsfeedViewController)
Select push segue from popup of the control drag
Give Button a identifier of Button01 (This would find items array where eventFeed.eventType = #"Festival";) So for clarity Button01 = Find events with eventFeed.eventType = #"Festival";
Step I am stuck on. Not sure how to access or display the array created in AppDelegate.m didFinishLaunchingWithOptions paragraph. I thought cellForRowAtIndexPath in EventsFeedViewController would be responsible for being called and displaying the rows again.
Sample of array code AppDelegate.m
Events array created AppDelegate.m. I need to pull the event when clicking the push button segue.
_events = [NSMutableArray arrayWithCapacity:20];
//***************************************
// Event feed related area
//***************************************
SDEventsFeed *eventFeed = [[SDEventsFeed alloc] init];
eventFeed.eventTitle = #"Event Fest Test 1";
eventFeed.eventDescription = #"This is not to be missed";
eventFeed.eventStartTime = #"2:00 PM";
eventFeed.eventImage = [UIImage imageNamed:#"fest.jpg"];
eventFeed.eventType = #"Festival";
[_events addObject:eventFeed];
In the table view controller that you want to push to display the data, you will need to add a property to hold that data. Something like the following:
#property (nonatomic, strong) MyDataClass *myData;
Then in the view controller that you're pushing from (the one with the button that pushes the table view controller), you'll want to add a method - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender. You can implement it in a way like the following:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifierFromStoryboard"]) {
YourTableViewControllerClass *viewController = segue.destinationViewController;
viewController.myData = self.myData;
}
}
To pull the data from the AppDelegate you would need to do the following.
Make sure you import the AppDelegate.h into your class doing the segue.
You can create a NSMutableArray property in AppDelegate.h to hold the array data "eventArray".
This is just one possible solution.
ButtonSort.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Button01"]) {
YourTableViewControllerClass *viewController = segue.destinationViewController;
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
viewController.events = appDelegate.eventsArray;
}
}

transfer several variables to another ViewController

Tell me, please, how should i transfer several variables from one ViewController to another?
For example, i have
ViewControlle.m
- (void) transferVar{
int a = 10;
int b = 11;
}
and i want to transfer them to another ViewController (SecondViewController.m). What should i do?
you can add a property on the second view controller for every variable you want to pass (or an array to contain them all), then if you are making the segue on the storyboard use the method
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
and inside it make this
SecondViewController *svc = (SecondViewController *) segue.destinationViewController;
There you have the view controller you want to pass values so only save it
svc.yourArray = #[[NSNumber numberWithInt:a],[NSNumber numberWithInt:b]];
Also it is highly recommendable to add a segue identifier to the storyboard segue and check
if([segue.identifier isEqualToString: #"theIdentifier"])
to be sure it is the segue that you wanted
Now on the viewDidLoadMethod you can use them.
If you are not using the storyboard segue just assign the value after initiating the view.

How to properly use modal view controller with the xcode 4.2 storyboard

I was wondering how to properly use the storyboard to put up a view controller modally. Personally I prefer working with xibs, but it seems that the storyboard is gaining popularity and will be the way to go in the future.
The way I would normally put up a view controller modally would be like this: let's say we have ViewControllerA (A for short) and ViewControllerB (B for short).
I would then normally put a protocol in B.h specifying the delegate method when B wants to be dismissed and add the id<theProtocol> delegate field as an assign property. Assuming i'm busy in A and I want to present B modally, I would write:
B* b = [[B alloc] initWithNibName:#"B" bundle:nil];
b.delegate = self;
[self presentModalViewController:B animated:YES];
Using the storyboard, I know it's possible to put up a different view controller in a modal way by ctrl-dragging from a button to a viewcontroller and selecting modal as transition type. I'm just wondering though; where do I set the delegate of the new view controller? What's the correct practice of passing things to your modal view controller? I don't really know what the whole deal with Segues is...
Take a look at this tutorial
According to it, you should set the delegate as follows:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"AddPlayer"])
{
UINavigationController *navigationController =
segue.destinationViewController;
PlayerDetailsViewController
*playerDetailsViewController =
[[navigationController viewControllers]
objectAtIndex:0];
playerDetailsViewController.delegate = self;
}
}
Where #"AddPlayer" is the name of your 'modal' segue
Instead of using the navigation controller you could directly use the UIStoryboardSegue object passed in prepareForSegue. It has a property called destinationViewController which is the view controller that is being instantiated. I find that a lot cleaner.
This is an example.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"AddPlayer"])
{
PlayerDetailsViewController
*playerDetailsViewController =
(PlayerDetailsViewController *) segue.destinationViewController;
playerDetailsViewController.delegate = self;
}
}
IMO I think that storyboards are great because they function like a blueprint of your application. Also I've never liked nibs. =D

Resources