iOS: Call a method in MainWindow from a View? - ios

Simple question:
My MainWindows organize all Views I use.
When I click a button on view1 i want that view2 is shown.
How to manage this?

You typically manage the views within a UIViewController subclass. If you created the views with Interface Builder you must connect them to the view controller by an IBOutlet so you can access them in code. Then in the button handler method you can simply set the view's hidden property to YES to hide a view or NO to show it.

Related

How do I pass the UIButton pressed from my custom UIControl to my view controller?

I have a Custom UIControl with 3 UIButtons:
This UIControl is embeded in a UIView (the Yellow Rectangle) inside a view controller:
Every button has a different tag (tag1, tag2, tag3). I need to identify which button is pressed in the view controller.
I'm trying to use sendActionsForControlEvents in my UIControl to send it to the view controller.
[self.button1 sendActionsForControlEvents:UIControlEventTouchUpInside];
[self.button2 sendActionsForControlEvents:UIControlEventTouchUpInside];
[self.button3 sendActionsForControlEvents:UIControlEventTouchUpInside];
I don't know how to receive it in my view controller and how to identify which button is pressed.
Can anyone help me?
Thanks.
I solved creating #property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *tabsCollection; in my UIControl.
Then in my ViewController I create a loop to iterate this IBOutletCollection and adding an action on each button to control the touch event.
for (button in self.customTabsComponent.tabsCollection) {
[button addTarget:self
action:#selector(tabPressed:)
forControlEvents:UIControlEventTouchUpInside];
}
Firstly, define the responsibilities.
If you develop a custom control that manages a collection of buttons it should be responsible for receiving the actions in those buttons and forwarding them to the view controller via its own interface.
Your view controller should have no responsibility of managing those buttons at all.
Otherwise, if the responsibility of managing the buttons, hence the code, is inside your view controller, then your custom control is not self-contained, not a reusable control. You simply won't be able to use it with another view controller without copy-pasting that code inside your view controller that makes the button work.
Now, if you custom control is a subclass of UIControl you cannot use sendActionsForControlEvents to pass information which button was tapped, since this interface is designed to have one action, but for different event types. That you need is different actions, or some kind of additional information that indicated which buttons was tapped.
Look at UIAlertController for example. One of the ways would be to implement a dynamic array of actions, which would be created in your view controller, passed to your custom control and invoked by the buttons. Your buttons would need to allocated dynamically inside your custom control. A bit more work, but this would be the most appropriate approach.
If you want to have a static set of buttons, you can add properties of block type to your custom control. Different buttons would invoke different blocks.
Alternatively, you can make a new delegate protocol and pass the index of pressed button, see UIAlertViewDelegate. This is a bit old school approach, which was used before blocks became available.

Navigate to UIViewController from a UIView

My app header is currently a full width, 65pt height UIView which I then use as a generic header for all pages.
class AppHeader: UIView {
...
}
Then, in my Main.storyboard I have a UIViewController with a View from the object library which has its class specified as AppHeader.
My AppHeader (UIView) has multiple buttons which should, if clicked, take you to from the page/controller you're currently on to another.
From the AppHeader class I do not have access to use the present method to show another controller as its not within scope.
Here is my AppHeader.xib:
How can I resolve this?
This is very bad behaviour, you should not use a UIView as a header. You should add a Navigation View Controller as the first view controller of your app. Navigation view controller has the navigation bar where you can put the buttons you want there. From that ones, you will be able to push or present other view controllers.
Check the official documentation: https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html
Make your AppHeader view a custom subclass of UIView if it isn't already. Wire the actions on the button to IBAction methods in the view.
Create a protocol AppHeaderDelegateProtocol. Give your AppHeader class a weak delegate property. Define methods in that protocol that let the AppHeader notify it's owning view controller about button presses.
Implement your AppHeaderDelegateProtocol in view controllers that will contain instances of AppHeader.
Connect the delegate property to each instance of AppHeader's owning view controller.
That should do it.
You can create a protocol - call it AppHeaderDelegate or something - and set up your other viewControllers to adopt that protocol. You could define functions to let your delegate know that a certain button was pressed, and your delegate viewController can react to that by presenting the correct view controller.
Apple's docs on protocols here.
Alternatively, you can use NotificationCenter to broadcast notifications to let subscribers know that a certain button was pressed, and have your viewControllers listening for these notifications and reacting to them accordingly. You have to manage when classes start/stop listening, though, as you may have several objects trying to react to a single notification.

Use XLForm with a toolbar

I want to launch a XLForms view controller as a Form Sheet. I want the controller to have a toolbar at the top and then the XLForm tableview underneath it. How?
The view controller isn't a navigation controller and so I need to add a toolbar at the top (or bottom) where I can add buttons. So how do I do this?
It turns out that this is not too difficult. I just wish that it was documented somewhere.
All the sample code I could find showed the top view controller inheriting from XLFormViewController. In this case, the IB controller only requires a topline view.
I wanted to expand the view controller to have other components in it other than just a "View" object. I wanted a toolbar across the top and a couple of other things.
So, here's how I did it. I'm not sure that this is the best approach but it did work.
Create the View Controller in IB and add all the components you want.
Include a TableView object someone in your design
Go into the "Assistant Editor" and hook the TableView object to the "tableView" object defined in XLFormViewController.h by ctrl-dragging and dropping on the IBOutlet tableView object.
All other controls work as usual.
Important:
Do not treat the tableView object like a regular object. In other words, do not implement UITableViewDataSource and UITableViewDelegate methods.
Hope this helps.

Global access to view properties

A containerView1 with 3 buttons which will need their text changed and their visibility modified according to user interaction with views in a different containerView2.
Each containerView has its viewController and there is the main viewController for the main storyBoard. The buttons will need to be Outlets as well as Actions.
Since the buttons are in a container whose controller is embedded segue, no prepareForSegue is allowed since there is no "segueing" here since the embed type is called during setup only.
What mechanise is best fit to be able to access the properties of the buttons from anywhere and how to implement it?
thanks

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.

Resources