Navigate to UIViewController from a UIView - ios

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.

Related

How to Navigate from a UIView class to a UIViewController?

I have a UIView which I am using as a seperate module and can include it anywhere I want to. Now I want to navigate to a UIViewController on click of the button inside the UIView.
Hope this is pretty clear.
Short answer: You shouldn't. You need to read up on the MVC design pattern. A UIView is a view object. You are trying to add controller behavior to a view object.
You should take a look at parent/child view controllers, container views, and embed segues. You could easily create a view controller that manages a "tile" inside another view controller, and sends messages to it's parent when the user taps buttons. This is a very common way of doing things.
The best way to do this is to supply the ViewController to the view as a delegate, conforming to a protocol you create for it.
For instance, if you UIView is used to pick an image, then the delegate should have a method akin to:
(void)view:(UIView*)view choseImage:(UIImage*)image;

Using Delegates with PageViewController

I have a PageViewController that has 3 child views contained within. I would like to see a simple Objective-C example using protocols/delegates for how I can trigger a method of the PageViewController when a user clicks a button in the child view controllers?
What you want is a simple delegation. You can create a page based project which will generate the code for you. After that create the protocol you want with its methods and add a delegate property to the Page child view controller. The only change you need to make is inside the pageViewController:viewControllerBeforeViewController and pageViewController:viewControllerAfterViewController methods. Before you return the page child controller there set also the delegate and implement the methods from the protocol.

IOS: What is the correct way to change a view from the class of a different view?

I have a UIImageView subclass (in swift) set up so I can access touchesBegan/touchesMoved/touchesEnded.
When one of these methods is called, I need to change a property of a different, loaded view.
It seems to me that I will now need to access the active view controller in order to set the properties of this other view. Is there are better way to go about this (such as event methods called in the view controller)?
Note that I'm new to iOS and I am not extremely familiar with the event system yet, as most information I've found is written in Objective C and not in Swift. (Don't worry, I'm looking through Apple's Documentation.)
Also, no, I can't change the UIImageView to a UIButton. Even if I changed to a UIButton, I need access to the individual touchesBegan, etc. methods and the same problem would persist.
If I'm understanding you correctly, you need to reference the UIViewController from the UIImageVIew to push/present a new UIViewController. You have a few options:
Fire an NSNotification from the image view and have an event listener on the view controller.
Create a delegate on the image view that fires a selector on the view controller.
Hold a reference to the view controller on the image view, and push a new view controller from the image view with that reference.
Modally present a new view controller on the application window's rootViewController.

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.

In IB, Cannot Connect IBOutlet Delegate to Another View Controller?

I have a view controller which as one of its views a container view (in IB storyboard) which embeds a table view controller, which in turn has a container view that embeds yet another view controller. In this last view controller I set up a delegate protocol with a weak synthesized delegate property as an IBOutlet. The very first view controller is what I want to receive the delegate methods from the last and I added the protocol <...> to it.
The problem is that I have not figured out a way while in storyboard (or otherwise) to link the IBOutlet delegate of the last view controller to the first view controller which follows the protocol so the last can send the first messages. I thought I could just drag and drop (with the control key) but all I find is segue options on the destination. It seems even though the delegate appears in the outlet connections window, it will not connect to ANY view controller in my project.
Can't ANY view controller be a delegate of another's protocol? And can be linked in IB? If I cannot do it with IB, I don't know how to make another VC a delegate upstream.
Any advice would be appreciated. Thanks.
You cannot connect IBOutlets between view controllers. You need to do it in code. You'll have to go through the chain of childViewController to get from the first controller to the last -- if I understand your structure properly, from the first view controller:
LastController *last = ((UIViewController *)self.childViewControllers[0]).childViewControllers[0];
last.delegate = self;
I asked a similar question Interface Builder won't allow connections to custom UIView class? I ultimately opened a bug with Apple. After a few follow up queries from Apple, I haven't heard any kind of resolution.

Resources