我的应用程序的大部分代码都在名为 MyViewController 的'm'文件中。该应用程序实现了一个包含UIWebView对象的自定义UIView。 UIView和UIWebView的代码保存在一个名为 CustomUIView 的单独“m”文件中。
我已设法使用委托覆盖UIWebView对象中的URL超链接的点击次数。但是,我希望这些点击启动一个存储在我的主应用程序代码中的方法。此方法称为“popupView”,并采用单个参数“inputArgument”。 inputArgument是用户单击的URL的文本。实际上,这种方法与导致我的自定义UIView启动的方法完全相同。
无论如何,我想要做的是让我重写的URL点击导致 popupView 方法启动,从而导致另一个UIView在点击的那个上面打开。
问题是检测到URL点击的'm'文件无法看到'popupView'方法,因为它包含在 MyViewController 'm'文件中。如何从另一个'm'文件中调用 popupView 方法?
答案 0 :(得分:2)
MyViewController
中声明-popupView:
的方法MyViewController.h
。#import
MyViewController.h
位于CustomUIView.m
。
CustomUIView
提供MyViewController
个[{1}}实例的引用,例如@property
中声明的CustomUIView.h
。对于(1)
,@interface
的{{1}}(MyViewController
)应该看起来有点像这样
MyViewController.h
对于@interface MyViewController : UIViewController
{
//....
}
- (void)popupView:(NSString *)urlText;
//....
@end
,(2)
应该在顶部附近的某处
UIViewController.m
对于#import "CustomUIView.h"
#import "MyViewController.h"
,(3)
中的@interface
应该类似于
CustomUIView.h
在创建@interface CustomUIView : UIView
{
//....
}
@property (nonatomic, weak) MyViewController *viewController;
@end
所拥有的CustomUIView
实例后,需要设置此属性。如果您的MyViewController
位于CustomUIView
,则可以通过将关键字MyViewController.xib
添加到属性声明中来设置此属性
IBOutlet
并将此属性指向@property (nonatomic, weak) IBOutlet MyViewController *viewController;
中的“文件所有者”。相反,如果您以编程方式创建XIB
,则可以在初始化后立即在其上设置此属性。
然而,这远非一种最佳做法。使用delegate pattern会好得多。要做到这一点,你需要
CustomUIView
添加到@property
。CustomUIView
。MyViewController
实例拥有的@property
实例的“委托”CustomUIView
设置为MyViewController
个实例。让我们将我们的委托协议称为像MyViewController
这样具有想象力的东西。对于CustomUIViewDelegate
,我们会将其声明在(1)
的顶部,如下所示:
CustomUIView.h
请注意,我们必须forward declare我们的类@class CustomUIView;
@protocol CustomUIViewDelegate <NSObject>
- (void)customUIView:(CustomUIView *)customView didSelectURLText:(NSString *)urlText;
@end
,以便编译器能够理解协议方法CustomUIView
中第一个参数的类型。
对于customUIView:didSelectURLText:
,我们会做一些与上面的(2)
非常相似的事情:您的(3)
CustomUIView
看起来像
@interface
同样,如果我们要在Interface Builder中设置此属性,我们需要使用@interface CustomUIView : UIView
{
//....
}
@property (nonatomic, weak) id<CustomUIViewDelegate> *delegate;
@end
关键字向IB宣布:
IBOutlet
对于(3),我们需要在适当的时间在委托对象@property (nonatomic, weak) IBOutlet id<CustomUIViewDelegate> *delegate;
上调用委托方法customUIView:didSelectURLText:
。
在你的问题中,你写了
我已设法使用委托来覆盖UIWebView对象中的URL超链接的点击次数。
所以,让我们说self.delegate
有一个实例方法
CustomUIView
当用户在UIWebView中选择一个链接时,你调用。需要告知- (void)didSelectURL:(NSURL *)url
{
//....
}
的代表:
CustomUIView
请注意,我们首先检查- (void)didSelectURL:(NSURL *)url
{
//...
if ([self.delegate respondsToSelector:@selector(customUIView:didSelectURLText:)]) {
{
[self.delegate customUIView:self didSelectURLText:url.absoluteString];
}
}
实例的委托对象是否通过调用CustomUIView
来实现感兴趣的选择器(customUIView:didSelectURLText:
)。
对于respondsToSelector:
,我们需要首先将(4)
添加到<CustomUIViewDelegate>
的{{1}}声明,并确保{{1 }} MyViewController
到我们使用符号@interface
的文件中。我们的#import
CustomUIView.h
看起来像这样:
CustomUIViewDelegate
更重要的是,我们需要在MyViewController
的{{1}}中实施 @interface
协议;到目前为止,我们只宣称#import "CustomUIView.h"
@interface MyViewController : UIViewController <CustomUIViewDelegate>
{
//....
}
//....
@end
采用了它。
为此,由于我们的协议只包含一种方法,因此我们只需添加自己的CustomUIViewDelegate
实现。我们的MyViewController
@implementation
看起来像这样:
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)
与其delegate
实例的关系,以描述如何明确地做到这一点,但我将提供一个示例:我将假设您以编程方式,在{ {1}}将CustomUIView
添加为MyViewController
视图的子视图。所以MyViewController
的实现看起来有点像这样:
CustomUIView
此时剩下要做的就是将局部变量-[MyViewController loadView]
的{{1}} CustomUIView
设置为MyViewController
:
-loadView
修改:根据- (void)loadView
{
[super loadView];
//....
CustomUIView *customView = //....
//....
[self.view addSubview:customView];
//....
}
和delegate
之间关系的新信息更新(5)。
在您的评论中,您写道@property
被添加为customView
的子视图,其中self
是customView.delegate = self;
中CustomUIView
的实例方法MyViewController
。因此,您注意到撰写CustomUIView
与撰写cvc.view
相同,这显然不是您想要做的。
您希望将cvc
的{{1}}属性设置为CustomUIViewController
的实例。因此,您的方法CustomUIView
应该类似于
-[CustomUIView show]
其中customView.delegate = self;
是self.delegate = self
的实例。
答案 1 :(得分:0)
好吧,既然你正在编写CustomUIView
,为什么不实现像initWithPopupDelegate:(MyViewController *)delegate
这样的构造函数,并在实例变量中保持对MyViewController
实例的引用,然后调用方法在那。
(在@class MyViewController;
顶部添加CustomUIView.h
,在#import "MyViewController.h"
顶部添加CustomUIView.m
,以便编译器知道您正在使用的课程。)
或者,如果只有一个MyViewController
实例,则可以为MyViewController
定义一个类方法,例如+ (MyViewController *)instance
,并返回对一个实例的引用(您存储在类变量中并在创建实例时第一次设置,请参阅“单例模式”)。但是,如果不知道代码的具体细节,我建议第一个解决方案(委托)更简单,更灵活。