0

我的应用程序的大部分代码都在一个名为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方法?

4

2 回答 2

2

直接地

  1. 中声明MyViewController的方法-popupView:MyViewController.h
  2. #import MyViewController.hCustomUIView.m.
  3. 提供CustomUIView对 的 [one] 实例的引用MyViewController,例如通过在 中@property声明的方式CustomUIView.h

对于(1)@interface( MyViewControllerin MyViewController.h) 应该看起来有点像这样

@interface MyViewController : UIViewController
{
    //....
}
- (void)popupView:(NSString *)urlText;
//....
@end

对于(2),UIViewController.m应该在顶部附近的某个地方有以下内容

#import "CustomUIView.h"
#import "MyViewController.h"

因为(3)@interfaceinCustomUIView.h应该看起来像

@interface CustomUIView : UIView
{
    //....
}
@property (nonatomic, weak) MyViewController *viewController;
@end

CustomUIView在创建owned by实例后的一段时间内,需要设置此属性MyViewController。如果您CustomUIView是 in MyViewController.xib,则可以通过将关键字添加IBOutlet到属性声明中来设置此属性,如下所示

@property (nonatomic, weak) IBOutlet MyViewController *viewController;

并将此属性指向XIB. 相反,如果您以CustomUIView编程方式创建,则可以在初始化后立即在其上设置此属性。

代表

然而,这远非最佳实践。使用委托模式会好得多。为此,您需要

  1. 定义一个委托协议
  2. 添加一个“代表”@propertyCustomUIView.
  3. 在适当的时候调用委托对象的委托方法。
  4. MyViewController.
  5. @property将实例所CustomUIView拥有的实例的“委托”设置MyViewControllerMyViewController实例。

让我们将委托协议称为富有想象力的东西,例如CustomUIViewDelegate. 对于(1),我们将在顶部声明CustomUIView.h如下:

@class CustomUIView;

@protocol CustomUIViewDelegate <NSObject>
- (void)customUIView:(CustomUIView *)customView didSelectURLText:(NSString *)urlText;
@end

请注意,我们必须前向声明我们的类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),我们需要在适当的时候调用customUIView:didSelectURLText:委托对象的委托方法。self.delegate

在你的问题中,你写了

我已经设法使用委托覆盖对 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实例的委托对象是否customUIView:didSelectURLText:通过调用感兴趣的选择器 ( ) 来respondsToSelector:实现它。

对于(4),我们首先需要添加<CustomUIViewDelegate>toMyViewController@interface声明,并确保添加到#import CustomUIView.h我们使用符号的文件中CustomUIViewDelegate。我们MyViewController的 '@interface看起来像这样:

#import "CustomUIView.h"

@interface MyViewController : UIViewController <CustomUIViewDelegate>
{
    //....
}
//....
@end

更重要的是,我们需要在's中实现CustomUIViewDelegate协议;到目前为止,我们只宣布采用它。MyViewController@implementationMyViewController

为此,由于我们的协议仅包含一种方法,因此我们只需要添加自己的-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实例的属性。我对' 与其实例的关系知之甚少,无法明确描述如何执行此操作,但我将提供一个示例:我假设您以编程方式将 '添加为' 视图的子视图。所以你的实现看起来有点像这样:CustomUIViewMyViewControllerMyViewControllerCustomUIView-[MyViewController loadView]CustomUIViewMyViewController-loadView

- (void)loadView
{
    [super loadView];
    
    //....
    
    CustomUIView *customView = //....        
    //....
    [self.view addSubview:customView];
    
    //....
    
}

此时剩下要做的就是delegate @property将局部变量的设置customViewself

customView.delegate = self;

编辑CustomUIView:根据有关和之间关系的新信息更新(5)MyViewController

在您的评论中,您写道您CustomUIView被添加为cvc.viewwhere cvcis an instance of CustomUIViewControllerinCustomUIView的子视图-[CustomUIView show]。因此,您注意到写作customView.delegate = self;与写作相同self.delegate = self,这显然不是您想要做的。

您想将CustomUIView' 的delegate属性设置为 的实例MyViewController。因此,您的方法-[CustomUIView show]应该类似于

- (void)show
{
    //....
    [cvc.view addSubview:self];

    self.delegate = mvc;
}

mvc的实例在哪里MyViewController

于 2012-10-31T00:35:35.490 回答
0

好吧,既然您正在编写CustomUIView,为什么不实现一个构造函数,并以这种方式在实例变量中initWithPopupDelegate:(MyViewController *)delegate保留对实例的引用,然后在其上调用该方法。MyViewController

@class MyViewController;在顶部CustomUIView.h#import "MyViewController.h" 顶部添加,CustomUIView.m以便编译器知道您正在使用的类。)

或者,如果只有一个MyViewController实例,您可以为 定义一个类方法MyViewController,例如,+ (MyViewController *)instance并让它返回对一个实例的引用(您将其存储在类变量中并在创建实例时第一次设置,参见“单例模式”)。但是在不知道代码细节的情况下,我建议第一个解决方案(委托)更简单、更灵活。

于 2012-10-31T00:35:15.333 回答