The bulk of the code for my app is in a ‘m’ file called MyViewController. The app implements a custom UIView which contains a UIWebView object. The code for the UIView and UIWebView is kept in a separate ‘m’ file called CustomUIView.
I have managed to override clicks on URL hyperlinks in the UIWebView object using a delegate. However, I would like to have these clicks launch a method that is stored in my main app code. This method is called “popupView”, and takes a single argument, “inputArgument”. The inputArgument is the text of the URL the user clicks on. In fact, this method is the very same one that causes my custom UIView to launch.
Anyway, what I’d like to do is have my overridden URL clicks cause the popupView method to launch, thus causing another UIView to open on top of the one that was clicked on.
The problem is that the ‘m’ file where the URL clicks are detected can’t see the ‘popupView’ method as it is included in the MyViewController ‘m’ file. How do I call the popupView method from another ‘m’ file?
Directly
MyViewController‘s method-popupView:inMyViewController.h.#importMyViewController.hinCustomUIView.m.CustomUIViewa reference to the [one] instance ofMyViewController, for example by way of an@propertydeclared inCustomUIView.h.For
(1), the@interfaceofMyViewController(inMyViewController.h) should look a bit like thisFor
(2),UIViewController.mshould have the following somewhere near the topFor
(3), the@interfaceinCustomUIView.hshould look something likeThis property will need to be set some time after the instance of
CustomUIViewowned byMyViewControlleris created. If yourCustomUIViewis inMyViewController.xib, you can set this property on it by adding the keywordIBOutletto the property’s declaration like thisand pointing this property to "File’s Owner" in the
XIB. If instead, you create theCustomUIViewprogrammatically, you can set this property on it as soon as you have initialized it.Delegate
This, however, is far from being a best practice. It would be much better to make use of the delegate pattern. To do this, you’ll need to
@propertytoCustomUIView.MyViewController.@propertyof the instance ofCustomUIViewowned by theMyViewControllerinstance to be theMyViewControllerinstance.Let’s call our delegate protocol something imaginative like
CustomUIViewDelegate. For(1), we’ll declare it at the top ofCustomUIView.has follows:Notice that we’ve had to forward declare our class
CustomUIViewso that the compiler is able to make sense of the type of the first argument in the protocol methodcustomUIView:didSelectURLText:.For
(2), we’ll do something quite similar to(3)above: YourCustomUIView@interfacewill look something likeAgain, if we’re going to set this property in Interface Builder, we’ll need to use the
IBOutletkeyword to announce it to IB:For (3), we need to call the delegate method
customUIView:didSelectURLText:on our delegate objectself.delegateat the appropriate time.In your question, you wrote
So, let’s say that
CustomUIViewhas an instance methodwhich you call when the user selects a link in the UIWebView. The
CustomUIView‘s delegate needs to be informed of this:Notice that we check first whether the
CustomUIViewinstance’s delegate object implements the selector of interest (customUIView:didSelectURLText:) by callingrespondsToSelector:on it.For
(4), we’ll need first to add<CustomUIViewDelegate>toMyViewController‘s@interfacedeclaration and be sure to#importCustomUIView.hinto the file where we use the symbolCustomUIViewDelegate. OurMyViewController‘s@interfacewill look something like this:More importantly, we need to implement the
CustomUIViewDelegateprotocol inMyViewController‘s@implementation; so far we’ve only declared thatMyViewControlleradopts it.To do this, since our protocol consists of only one method, we’ll need only to add our own implementation of
-customUIView:didSelectURLText:. OurMyViewController‘s@implementationwill look something like this:Finally, for
(5), we’ll need to set thedelegateproperty of the instance ofCustomUIViewowned by theMyViewControllerinstance. I don’t know enough aboutMyViewController‘s relationship with itsCustomUIViewinstance to do describe how to do this definitively, but I’ll provide an example: I’ll assume that you programmatically, in-[MyViewController loadView]add theCustomUIViewas a subview ofMyViewController‘s view. So your implementation of-loadViewlooks a bit like this:All that remains to do at this point is to set the
delegate@propertyof the local variablecustomViewtoself:Edit: Updated (5) in light of new information about the relationship between
CustomUIViewandMyViewController.In your comment, you write that your
CustomUIViewis added as a subview ofcvc.viewwherecvcis an instance ofCustomUIViewControllerinCustomUIView‘s method-[CustomUIView show]. On account of this, you note that writingcustomView.delegate = self;is the same as writingself.delegate = self, which is clearly not what you want to do.You want to set the
CustomUIView‘sdelegateproperty to be the instance ofMyViewController. Consequently, your method-[CustomUIView show]should look something likewhere
mvcis the instance ofMyViewController.