I'm finding some difficulties here. I'm setting up an UITableView where users can add stuff to. I'm done with the AddViewController, where users can get to by pressing the + on the UIBarNavigationButton, and then Push Segue to my AddViewController.
Here in my AddViewController is an Array where the user's data is stored in. Now how do I get the data in my UITableView in my FirstViewController array? I was thinking with another Push Segue from the Save UIBarNavigationButton and pushing the User array into the TableView Data?
Is this the right way to do it?
Kind Regards
Following along with what Tander said, you should use an unwind segue not push. Follow this example as a general guideline.
Use a similar setup like this in your FirstViewController:
//FirstViewController.m
- (IBAction)setArrayFromPreviousController:(UIStoryboardSegue *)segue
{
AddViewController *controller = [segue sourceViewController];
//old array and new array are the two array variable names
[self setOld_array:[controller new_array]];
}
Alternatively, you could use a protocol method along with a delegate. This is a little bit more complex:
A great tutorial on how to accomplish this can be found here.
If you're asking if you should use a push segue to move data back to previous controller, the answer is no.
What you can do is use unwind segues for this:
https://developer.apple.com/library/ios/technotes/tn2298/_index.html
For transforming data from B ViewController to A ViewController, you can use Unwind Segue, Protocols and Delegate and also Blocks.
Here i am showing you how to transform data using Protocol & Delegate.
In B VC, in H file add
1) Just above #interface:
#protocol addDataProtocol <NSObject>
-(void)addData:(NSArray *)arrayData;
#end
2) dd property
#property(nonatomic,retain)id<addDataProtocol>delegate;
3) In the M file, just before [self.navigationController popViewControllerAnimated:YES]; add:
[self.delegate addData:yourArray];
4) In A VC:
confirm the delegate before pushing, like : objBViewController.delegate=self;
5) Call the method:
-(void)addData:(NSArray *)arrayFromB
and access arrayFromB.
On your TVC you have to create an action which accepts a UIStoryboardSegue (I think). On you AddVC you can ctrl-drag the exit button to the little green icon on the storyboard scene. You then conect one with another. All you have left to do is to implement prepareForSegue on AddVC so you can pass your array back to the TVC. BTW, the action on TVC should also accept the array you're passing.
You can do a search on youtube, there must be a bazilion of tutorials about it.
Related
There are a lot of stuff on the net according the topic but I don't get it. I have an App with Custom segue implementation and without Navigation controller. There are cases in which I need to unwind back several steps.
For implementation I use simple calls:
CODE CUSTOM SEGUE
For wind:
[[self sourceViewController] presentModalViewController:[self destinationViewController] animated:YES];
For unwind:
[[self destinationViewController] dismissViewControllerAnimated: YES completion: nil];
As I understand when I wind segue somewhere in the memory there is data which is used during the unwind. For that reason in the custom unwind I only use read only property destinationViewController.
So how can I unwind several steps back in one action? Or I have to make several unwinds in different View controllers?
I read the following question, but I don't understand implementation.
Bellow I put example of my apps logic:
EXAMPLE
I have 4 VC which is in a chain:
VC A -> VC B -> VC C -> VC D
I wind and unwind back and forth. The logic is ok. There are situation in which I need to unwind back from VC D to VC B. How to do that? Can I unwind directly to VC B or I have to unwind to VC C and then in the unwind handler to unwind to VC B?
I also thought of additional segue from VC D to VC B, but there are remarks on the net that this is not the right way, because segue chain will get messy.
The answer to What are Unwind segues for and how do you use them? has everything you need to know about unwindSegues (I suggest you re-read it).
But for a more direct answer, yes you can unwind back from VC D to VC B. To do that you have to first implement the method in VC B:
- (IBAction)unwindToVCB:(UIStoryboardSegue *)unwindSegue
{
}
after doing so, go to the IB, and control-drag a button's action to the Exit icon, you should then pick the method you created above as the selector. (This is taken directly from the question/answer stated above).
Again, for a clearer version of what I said, read the answer of the linked question I mentioned above.
You have to use UINavigationController, just add it in storyboard as mainViewController and set 'A' ViewController as root view controller for it, then change all segues to push segue, set 'Identifires' for them, and you can use performSegueWithIdentifire to push view controller and inside view controller:
[self.navigationController popViewControllerAnimated:];
or
[self.navigationController popToViewController: animated:];
to dismiss it.
I'm know how to use storybaord drag line to exit use unwind method.
I have four uiviewcontroller (A~D).
I write the code in B UIViewcontroller
-(IBAction) backToMenu:(UIStoryboardSegue *) segue
{
}
I know It's can drag the action to the green button(exit) to set the back action in the D UIViewcontroller.
It will show the backToMenu method name and they can link.
Now, I want to use programming to implement the drag to green button (exit) action.
But I don't know how to write this part.
I don't use popViewControllerAnimated method. because I need from D UIViewcontroller back to the B UIviewcontroller.
And D UIviewcontroller have a condition if a variable is YES, will unwind to the B(backToMenu) method.
Have any one know how to use the code implement the "drag line to the exit button" action?
(I am use navigation push, not modal)
Thank you very much.
You should've read the docs.
[self.navigationController popToViewController:vcB animated:YES];
I have a form and it gives users an advance mode. I've already googled and looked around at different SO questions (sharing data between controllers, protocols, and passing data between segues) but I'm wondering if there's a better way.
Is there a way for me to have some sort of "master controller" that holds all the data while going back and forth between 3 different controllers?
If I can just hold the data for the second controller and allow my user to make that quick advance edit in the third while keeping it's data intact, that'll do for now.
Thanks in advance
Here's a quick walkthrough of my app:
FirstViewController: User selects an option
SecondViewController: User does some editing while storing that option
(*Optional)ThirdViewControl: User one more quick edit using a web view
*xcode5/iOS7
If you are passing data from one view controller to the next and you are using segues, then call a method on the next view controller in line from prepareForSegue. For example, when segueing between ViewController1 and ViewController2, add this code to ViewController1 and repeat as necessary in other view controllers:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewController2 *viewController = segue.destinationViewController;
[viewController configureWithSomeState:self.someState];
}
This code assumes that someState is a property defined on ViewController1.
EDIT: One thing you could do--although I do not like this approach because it forces your VCs to have special knowledge about their parent controller--is to derive UINavigationController, then in your storyboard, use the new class for your navigation controller. Store the state in the derived navigation controller and access it from each VC like this:
DerivedNavigationController *navigationController = (DerivedNavigationController *)self.navigationController;
navigationController.someState...;
Typically I'd put information that is used throughout the application in the application delegate where everybody has access to it.
Another possibility is to implement a singleton data management class to hold it for you.
In this case it seems like the application is really a pretty linear flow, so I'd just pass the selection from vc1 to vc2 and then again to vc3 in the respective prepareForSegue calls.
I have an application in storyboard and make the connections to second view controller by push operation in the storyboard itself(without using coding).
Is there any way to pop to first view controller without writing any code and using the storyboard?
Note:by using navigation controller we will have back button but if a button is created in the second view controller and when we tap on that button we should pop to first view controller.
Storyboards don't provide a way to return from a segue without coding, but this can be easily accomplished with this code:
[self.navigationController popToRootViewControllerAnimated:YES];
Storyboards doesn't provide a "no-code" way to popViewController, you need to implement by yourself.
And if you want to pop to the first viewController you need to use:
[self.navigationController popToRootViewControllerAnimated:YES];
You can use an UnwindSegue as well since iOS6, although it does require some code)* for push segues. For a good explanation of UnwindSegues, see SO post, scroll down to "In a Nutshell"
)*Specifically, you need an unwind action, e.g.
- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
A solution that involves writing code once but can be used afterwards in your storyboards as a segue without further implementations would be some kind of PopSegue as subclass of a UIStoryboardSegue.
#interface PopSegue : UIStoryboardSegue
Overwrite the -perform method as follows.
#implementation PopSegue
- (void)perform
{
[[self.sourceViewController navigationController] popViewControllerAnimated:YES];
}
#end
Use a custom segue for back-navigation and specify the PopSegue class.
Let's say I have a UILabel on ViewControllerA and and UITextField on ViewControllerB. I want to go to ViewControllerB and input text then press a button to go back to ViewControllerA. The UILabel should now read whatever was typed in the UITextField.
I was able to accomplish the above by using NSUserDefaults and also using delegation. I am using Storyboards to do this. My question is about the segues used in the storyboards.
It seems when using delegation I must go to and from the storyboard with code and not visually connect the view controllers with a segue in order for the data to transfer. Here is the code when I press a button on my ViewController A:
- (IBAction)pressFirstButton:(id)sender {
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
RBViewController2 *vc2 = [sb instantiateViewControllerWithIdentifier:#"ViewController2"];
[vc2 setDelegate:self];
[self presentViewController:vc2 animated:YES completion:NULL];
}
when passing the data back from ViewControllerB to ViewControllerA I do this:
- (IBAction)buttonSegueBackTo1:(id)sender {
NSString *sendThis = self.textFieldVC2.text;
[self.delegate passTextFieldInput:sendThis];
[self dismissViewControllerAnimated:YES completion:NULL];
}
No segue has been drawn between the view controllers and everything works fine. If I don't write this same code, and draw in a segue, the data won't pass backwards. However when I try passing data like this using NSUserDefaults I don't have to write the code to go to and from the view controllers. Instead I can simply connect the view controllers with a drawn segue. The weird thing is, if I'm trying to pass the data in using NSUserDefaults when manually coding the view controllers (an not drawing the segue) the data doesn't transfer.
I'm thinking maybe instead of writing the code in the -(IBAction) pressFirstButton:(id) sender method, I should be putting the code in the prepareForSegue method.
My question is why do drawn segues sometime cause data to be lost? Must all delegation be done without drawn segues? If NSUserDefaults require segues to transfer properly and delegation require code to transfer properly then if I have a view that requires both, it seems that NSUserDefaults will trump the delegation b/c the manual segue being used "resets" the view and only the NSUserDefaults data remains.
Normal segues (any other than unwind segues) ALWAYS create new view controllers. So, if you're using anything other than an unwind segue to go back to A, you're really not "going back", you're creating a new ViewControllerA. Unwind segues aren't normally used in a case like you're presenting, just going back one controller, but you could.
This situation also isn't a good place to use user defaults. The Apple recommended way, is to use delegation, like you do in the code your question. The way you show, is probably the best way to do it, rather than using a segue to go back. You certainly could use a segue to go forward though, and in that case you would implement prepareForSegue: so you can set yourself as the delegate and/or pass any data forward.
Your question is a little dense to parse but I think you are asking if there is a way to get pass data through segues. The answer is yes, and much better than the workarounds you are trying.
In your button you would call:
[self performSegueWithIdentifier:#"scrollerSegue" sender:self];
This will trigger the method below and it is here that you can set the data on the destination viewController. You can set abstract properties on the destination viewController but you can't populate an UIKit elements (labels, imageViews, etc.) because they don't exist yet. Instead set properties and then in viewWillAppear in the destination viewController, do the set up as needed. (alternatively, instead of passing data, you could just set the delegate and then call methods on the delegate to get the data as needed).
For getting data back, using the delegate and calling methods on it seems to be the Apple recommended way of doing things.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"scrollerSegue"])
{
ScrollViewController * target = segue.destinationViewController;
target.assetsArray = self.assetsArray;
target.delegate = self;
}
}