Getting access to UI elements from other class - ios

There is ViewController which contains elements such as
UIPickerView and two UITextFields.
There is PickerViewController, where UIPickerViewDelegate and UIPickerViewDataSource methods are implemented (didSelectRow, titleForRow, and the other ones).
After an element is selected in the UIPickerView, I need to change the text of one of the UITextFields. I can't do that, because didSelectRow: is implemented in PickerViewController but UITextField is contained in ViewController. How can I get access? And most importantly, how can I do that correctly?
Should I implement the picker methods in another class, or have them in ViewController?

how can I do that correctly?
This is a better question than simply how to let the PickerViewController change a text field in its parent view controller, because really it shouldn't.
Two possibilities spring to mind: the picker controller can pass some kind of message directly back to the other controller, or it can update a model, which the other controller reads from after the picker view is done.
The first is probably most easily accomplished by giving the picker controller an "after picking" handler Block that would have the necessary data as an argument, and that the parent controller defines and sets on the other. Before the picker controller is dismissed, it should call the Block, passing in the selection and performing whatever actions the other controller specified.
The second means that the parent controller and the picker controller must have access to the same data object. Without knowing what else is going on, it's hard to be exact, but one good possibility is that the parent controller actually gives the picker controller the model object that it should read from, rather than the picker controller acquiring it on its own. The picker controller just changes the object that it's passed.

You can add a UITextField properties to a PickerViewController and pass UITexiField instances from UIViewController:
in PickerViewController.h:
#property UITextField *textField1, *textField2;
in UIViewController.m:
PickerViewController *picker = [PickerViewController new];
picker.textField1 = self.textField1;
picker.textField2 = self.textField2;
You can implement PickerView anyway - in another class or in ViewController.

you can use custom delegate to update the textfield values.

Related

Using storyboarding in xCode how can I change the value of a label from a different view?

I'm writing an app that uses storyboarding and I want to update the labels in one view by clicking a button in a previous view.
_label.text = variable1;
is the line I would use to change the value of label, which is in the next view, when I click the button. Using this method I can easily change labels in the same view as the button but it does nothing when I go to the next view and see empty labels.
I've tried looking everywhere and found similar issues but couldn't find anything that worked for me so any solution would be very appreciated!
Unfortunately, it is not possible to connect IBOutlets between different scenes in storyboard.
It is difficult to suggest some precise solution because you have to provide more details about the setup which you have. Still, it is possible to outline some possible solutions:
Using prepareForSegue
If the view controller which you want to modify appears after the segue is performed you can customise its appearance in prepareForSegue function.
Using delegation
You can assign the view controller which wants to modify another view controller as its delegate. For example, if ViewController1 wants to modify ViewController2:
#interface ViewController1: UIViewController {}
#property (nonatomic,weak) ViewController2 *controllerThatIWantToModify;
with such setup you can call:
self.controllerThatIWantToModify.label.text = variable1;
You use storyboards, so there must be a segue from your first viewController (with the button) to your second (with labels in it).
If it is the case, you can set up the labels of the second view controller from the prepareForSegue method of your first view controller.
This method is called with a segue object which has a destinationViewController property which is your second view controller.
If you have several segue from this viewController, you should check if it is the right segue and then set it up.
To do that you need to set up outlets that gives you access to the labels from the viewController.
Then you can either write a setUpLabelsWith:(NSString)text1 ... method in your view controller, or directly access the outlets from the first view controller (supposing their are not private).
Yes this supposes your second view controller has a custom class.

PrepareForSegue between UIView and ViewController using Swift

I have a UIView in a view controller which displays an image. This UIView is associated to classX, while the view controller it is in is associated to classY.
My question is, how can I use prepareForSegue in the case? I want to send data from my viewController class to the UIView class to display an image depending on the value it receives respectively.
I have it this way because in classX I need to inherit the UIView class to display the pictures, while in classY I need to inherit the UIViewController because i have functions that need it there; from my knowledge, I cannot inherit both together.
Any thoughts on how to do this?
Thanks
Create an IBOutlet for the image view in your view controller so you can access it.
The view controller or any code in prepareForSegue can now access the image view and set its contents using whatever methods your image class provides.

Send the value in Class of ViewController to Class of View

Is there any way that could send the value in Class of ViewController to Class of View?
Because I want to make a drawing board and I made a modal scene to set values about color, width .
I know how to send the value in modal scene to my ViewController , but now I need use those value in Class of View , or not Class of ViewController.
Sounds like you need to devise a protocol to open a delegation channel between the two classes. Then when the modal VC wants to send data to its delegate (its presenter, in this case), it can of its own volition.
The View Controller can have a reference to the View, therefore the View Controller can simply pass the values to View by calling a View's method or updating View's properties. This is a common pattern: View defines a Protocol and data/requests from View to ViewController go through this Protocol (the ViewController acts as delegate of View); and ViewController owns the View.
For inspiration on how to implement a farily decoupled design applying this pattern, you can have a look at documentation on UICollectionView and UICollectionViewController.
Other options, depending on what design you need, are Key-Value Observing or Notifications.

Passing a variable from modal tableview to parent view

I have a detailView which has a button on it to bring up a tableView as a modal view to help the user giving a selection of names. I'm trying to figure out a simple way of passing the selected name to a textField on the parent detailView.
I have been building this project using Storyboard, but I am totally stuck at this point.
There are several ways to approach this kind of problem:
shared object: The parent view controller provides some object to the child that contains the state that the child is expected to work with and possibly modify. In this case, it might be a dictionary that contains an array of names to display and the index of the selected person.
child's properties: Often, the child view controller itself is the shared object. The parent instantiates the child, sets some of the child's properties (e.g. people and selectedPerson), and presents it. When the child is finished, the parent gets the properties of the child that it cares about (e.g. selectedPerson) before releasing it.
delegation: Sometimes the child view controller will need to interact with the parent in order to do its job. This is a good time to use delegation: establish some protocol that the child knows about and the parent implements, add a delegate property to the child, and have the parent set the child's delegate property to itself before presenting it. This way, the child can talk to the parent without depending on the parent class.
For the case you describe, where you just want to convey some piece of data back to the parent when the child is done, the second strategy above is the simplest.
Note: DetailViewController below should be replaced with whatever the class is of your detail view controller.
1) If you don't already have a subclass of UITableViewController, create one. This will allow you to add a property to the table view controller. Change the class of your modally presented controller in your Storyboard to this new subclass.
2) Add a property to your table view controller subclass like this:
#property (weak, nonatomic) id mydelegate;
3) In prepareForSegue in your DetailViewController, set the mydelegate property of the destination view controller to self which is a pointer to your parent detailView.
4) In your DetailViewController, create a method to receive the selected name:
- (void)userDidSelectName:(NSString *)name;
5) In the tableView:didSelectRowAtIndexPath method of your tableViewController subclass, get the name from the tableViewCell and call the userDidSelectName method on the delegate:
[self.mydelegate userDidSelectName:selectedName];
6) The correct way to to this would be to define a protocol that has a method userDidSelectName and then make the delegate pointer in step 2 require a class that implements that protocol. The quicker and dirtier thing to do is to make the delegate pointer in step 2 of type DetailViewController * instead of id. This will allow you to call userDidSelectName without the compiler complaining.

Data sent back to Uitableview

I have a UITableviewController and I push another UIViewController in 'didSelectRow..' method.
I have user input controls (combobox, stepper) in this viewController, that when the UIViewController is popped , I would like to receive the newly entered data in the UITableviewController (and update the tableview accordingly).
I saw some questions/answers, and some said to use "Delegation/Protocol" approach, but did not find any specific example how to achieve this.
Can someone help?
Create a new file for your project and choose the Protocol file type. (We'll call it CallBackProtocol.) In the view controller that you push, create a property that has a type of id<CallBackProtocol> delegate;. Have your table controller adopt the protocol and, when it creates the view controller, set controller.delegate = self;.
Define a method in the protocol that lets you pass whatever data you need back to the caller. Implement that method in the table controller and call it from the second view controller just before popping it.
(Or use a NSNotification.)

Resources