直接
- 在
MyViewController.h中声明MyViewController的方法-popupView:。
-
#importMyViewController.h 在CustomUIView.m。
- 为
CustomUIView 提供对MyViewController 的[one] 实例的引用,例如通过CustomUIView.h 中声明的@property。
对于(1),MyViewController(在MyViewController.h 中)的@interface 应该有点像这样
@interface MyViewController : UIViewController
{
//....
}
- (void)popupView:(NSString *)urlText;
//....
@end
对于(2),UIViewController.m 应该在顶部附近的某处有以下内容
#import "CustomUIView.h"
#import "MyViewController.h"
对于(3),CustomUIView.h 中的@interface 应该类似于
@interface CustomUIView : UIView
{
//....
}
@property (nonatomic, weak) MyViewController *viewController;
@end
这个属性需要在MyViewController 拥有的CustomUIView 实例创建后的一段时间内设置。如果您的CustomUIView 在MyViewController.xib 中,则可以通过将关键字IBOutlet 添加到属性声明中来设置此属性,如下所示
@property (nonatomic, weak) IBOutlet MyViewController *viewController;
并将此属性指向XIB 中的“文件所有者”。相反,如果您以编程方式创建 CustomUIView,则可以在初始化后立即在其上设置此属性。
委托
然而,这远非最佳实践。使用delegate pattern 会更好。为此,您需要
- 定义一个委托protocol。
- 将“代表”
@property 添加到 CustomUIView。
- 在适当的时候调用委托对象的委托方法。
- 在
MyViewController中实现协议。
- 将
MyViewController实例所拥有的CustomUIView实例的“委托”@property设置为MyViewController实例。
让我们将委托协议称为富有想象力的东西,例如CustomUIViewDelegate。对于(1),我们将在CustomUIView.h 的顶部声明如下:
@class CustomUIView;
@protocol CustomUIViewDelegate <NSObject>
- (void)customUIView:(CustomUIView *)customView didSelectURLText:(NSString *)urlText;
@end
请注意,我们必须 forward declare 我们的类 CustomUIView 以便编译器能够理解协议方法 customUIView:didSelectURLText: 中第一个参数的类型。
对于(2),我们将执行与上面的(3) 非常相似的操作:您的CustomUIView @interface 看起来像
@interface CustomUIView : UIView
{
//....
}
@property (nonatomic, weak) id<CustomUIViewDelegate> *delegate;
@end
同样,如果我们要在 Interface Builder 中设置此属性,我们需要使用 IBOutlet 关键字向 IB 宣布它:
@property (nonatomic, weak) IBOutlet id<CustomUIViewDelegate> *delegate;
对于(3),我们需要在适当的时候在我们的委托对象self.delegate上调用委托方法customUIView:didSelectURLText:。
在你的问题中,你写道
我已经设法使用委托覆盖了对 UIWebView 对象中的 URL 超链接的点击。
那么,假设CustomUIView 有一个实例方法
- (void)didSelectURL:(NSURL *)url
{
//....
}
当用户在 UIWebView 中选择一个链接时,你调用了哪个。 CustomUIView 的代表需要知道这一点:
- (void)didSelectURL:(NSURL *)url
{
//...
if ([self.delegate respondsToSelector:@selector(customUIView:didSelectURLText:)]) {
{
[self.delegate customUIView:self didSelectURLText:url.absoluteString];
}
}
请注意,我们首先检查 CustomUIView 实例的委托对象是否通过调用 respondsToSelector: 来实现感兴趣的选择器 (customUIView:didSelectURLText:)。
对于(4),我们需要首先将<CustomUIViewDelegate> 添加到MyViewController 的@interface 声明中,并确保将#import CustomUIView.h 添加到我们所在的文件中使用符号CustomUIViewDelegate。我们的MyViewController 的@interface 看起来像这样:
#import "CustomUIView.h"
@interface MyViewController : UIViewController <CustomUIViewDelegate>
{
//....
}
//....
@end
更重要的是,我们需要在MyViewController的@implementation中实现CustomUIViewDelegate协议;到目前为止,我们只声明 MyViewController 采用它。
为此,由于我们的协议仅包含一种方法,因此我们只需要添加自己的 -customUIView:didSelectURLText: 实现即可。我们的MyViewController 的@implementation 看起来像这样:
#import "MyViewController.h"
@implementation MyViewController
//....
- (void)popupView:(NSString *)urlText
{
//....
}
#pragma mark - CustomUIViewDelegate
- (void)customUIView:(CustomUIView *)customView didSelectURLText:(NSString *)urlText
{
[self popupView:urlText];
}
//....
@end
最后,对于(5),我们需要设置MyViewController 实例拥有的CustomUIView 实例的delegate 属性。我对MyViewController 与其CustomUIView 实例的关系知之甚少,无法明确描述如何执行此操作,但我将提供一个示例:我假设您以编程方式在-[MyViewController loadView] 添加CustomUIView 作为MyViewController 视图的子视图。所以你对-loadView 的实现看起来有点像这样:
- (void)loadView
{
[super loadView];
//....
CustomUIView *customView = //....
//....
[self.view addSubview:customView];
//....
}
此时剩下要做的就是将局部变量customView的delegate@property设置为self:
customView.delegate = self;
编辑:根据有关CustomUIView 和MyViewController 之间关系的新信息进行了更新 (5)。
在您的评论中,您写道您的CustomUIView 被添加为cvc.view 的子视图,其中cvc 是CustomUIView 的方法-[CustomUIView show] 中CustomUIViewController 的一个实例。因此,您注意到写customView.delegate = self; 与写self.delegate = self 相同,这显然不是您想要做的。
您希望将CustomUIView 的delegate 属性设置为MyViewController 的实例。因此,您的方法 -[CustomUIView show] 应该类似于
- (void)show
{
//....
[cvc.view addSubview:self];
self.delegate = mvc;
}
其中mvc 是MyViewController 的实例。