5

我有一个UIViewControllerwith 它UIView,其中包含一个UIButton. 我想UIViewController在按钮单击事件中触发一个方法。
保持参考UIViewController似乎不是一个好主意,如以下链接所述: Get to UIViewController from UIView?

所以我想使用委托来实现这一点。关于如何实现这一目标的任何提示?

4

7 回答 7

9

你可以做这样的事情

自定义视图.h

#import <UIKit/UIKit.h>
@protocol CustomViewDelegate <NSObject>

 -(void)didButtonPressed;

@end

 @interface CustomView : UIView

  @property (assign) id<CustomViewDelegate> delegate;

@end

自定义视图.m

#import "CustomView.h"
@implementation CustomView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
    // Initialization code
    self.backgroundColor = [UIColor whiteColor];

    //[self addSubview:titleLbl];
    UIButton *button= [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(100, 100, 100, 50);
    [button addTarget:self.delegate action:@selector(didButtonPressed) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"pressMe" forState:UIControlStateNormal];
    [self addSubview:button];


}
return self;
}

在你的ViewController.m

-(void)loadView
 {
  [super loadView];
  CustomView *view = [[CustomView alloc]initWithFrame:self.view.bounds];
  view.delegate = self;
  [self.view addSubview:view];

 }
于 2013-03-12T14:14:05.577 回答
3

这就是构建响应者链的目的。当您向按钮添加目标时,只需nil为目标提供:

[mySpecialButton addTarget:nil 
                 action:@selector(mySpecialButtonTapped:)
                 forControlEvents:UIControlEventTouchUpInside];

nil目标基本上意味着“发送mySpecialButtonTapped:到响应者链中可以处理它的任何对象” 。

现在您可以在响应者链中的任何位置处理此选择器,包括按钮本身、其包含的视图、其包含的视图控制器、UIApplication,最后是您的 AppDelegate。只需将此方法放在最适合您需要的对象中:

- (void)mySpecialButtonTapped:(id)sender {
    NSLog("My special button was tapped!");
}

如果您只想将消息冒泡,则不需要委托或回调块(如已接受的答案)。

于 2015-08-28T20:02:13.077 回答
1

我猜您期望一些更基本的东西,然后将一些按钮操作传递给控制器​​。在模型/视图/控制器协作的情况下,我总是遵循 MVC 模式。它解决了您的问题和许多其他问题。我想分享我的经验。

  1. 将控制器与视图和模型分开:不要将所有“业务逻辑”放入与视图相关的类中;这使得代码非常不可用。制作控制器类来托管此代码,但要确保控制器类不会对表示做出太多假设。
  2. 使用定义回调 API @protocol@optional如果不是所有方法都需要,则使用。
  3. 对于视图定义协议<view class name>Protocol(例如 NewsViewProtocol)。对于控制器定义委托<view class name>Delegate(例如 NewsViewDelegate)和数据<view class name>DataSource源(例如 NewsViewDataSource)。将所有这些@protocols 保存在一个名为的单独文件中<view class name>Protocol.h(例如 NewsViewProtocol.h)

简短的例子:

NewsView.h 的内容

//
// NewsView.h
@interface NewsView : UIView <NewsViewProtocol> {
@protected
     NSObject* delegate_;
     NSObject* dataSource_;
}
@end

NewsController.h 和 .m 的内容

//
// NewsController.h
@interface NewsController : UIViewController <NewsViewDataSource, NewsViewDelegate> {
}
@property (nonatomic, weak) UIView<NewsViewProtocol>* customView;
@end

@implementation NewsController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.customView = (UIView<NewsViewProtocol>*)self.view;
    [self.customView setDelegate:self];
    [self.customView setDataSource:self];
}
@end

NewsViewProtocol.h 的内容

//
// NewsViewProtocol.h
@protocol NewsViewProtocol;

@protocol NewsViewDelegate<NSObject>
@optional
- (void)someAction;
- (void)newsView:(UIView<NewsViewProtocol>*)newsView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
@end

@protocol NewsViewDataSource<NSObject>
@required
- (id)newsView:(UIView<NewsViewProtocol>*)newsView itemAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)numberOfItemsInNewsView:(UIView<NewsViewProtocol>*)newsView section:(NSInteger)section;
- (BOOL)newsView:(UIView<NewsViewProtocol>*)newsView shouldDisplaySection:(NSInteger)section;
@end

@protocol NewsViewProtocol<NSObject>
@required

//Never retain delegate instance into implementation of this method
- (void)setDelegate:(NSObject<NewsViewDelegate>*)delegate;
//Never retain delegate instance into implementation of this method
- (void)setDataSource:(NSObject<NewsViewDataSource>*)dataSource;
- (void)reload;
@end

你可能认为它是多余的。在简单的视图控制器中,是的。但是,如果您开发具有大量数据的非常复杂的屏幕,那么它会给您带来一些优势,例如:

  • 帮助您分离视图和控制器之间的责任。
  • 保持你的代码清晰。
  • 使您的代码更具可重用性。
于 2013-03-12T14:36:59.343 回答
0

在 xCode 中生活很轻松。

一开始请确保您的 xib 视图(其中带有按钮的视图)与正确的 ViewController 类相关联。它可以是新项目或您的自定义项目附带的默认 ViewController 类。

在这之后,魔术就来了!将您的视图分成 2 个面板。目标是查看您的 xib 和 viewController 代码(.m 文件)。现在按下键盘的控制键并将 UIButton 拖到代码中。选择 IBA 动作。它会生成一些你可以用其他语言称之为“听众”的东西。进入你的 View Controller 的核心代码,完成方法!

就这么简单!玩得开心 :)

于 2013-03-12T12:44:57.597 回答
-1

您实际上并不需要委托 - 这就是 UIButton 的用途。只需按住 Control 单击并从按钮拖动到 UIViewController 的 .m 文件。这将创建一个新方法。从那里,您可以调用您编写的方法,也可以将您拥有的内容复制粘贴到新方法中。

于 2013-03-12T12:42:24.093 回答
-1

以编程方式添加按钮,在 myViewController.m

UIView *yourView = [[UIView alloc] init];
UIButton *yourButton = [[UIButton alloc] initWithFrame:CGRectMake(0,0,100,21)];
[yourButton addTarget:self action:@selector(yourMethod) forControlEvents:UIControlEventTouchDown];
[yourView addSubview:yourButton];

更多信息在这里

于 2013-03-12T13:04:20.843 回答
-1

你可以试试这个:

[yourButton addTarget:self action:@selector(yourButtonAction:) forControlEvents:UIControlEventTouchUpInside];

并在您的选择器中指定操作

- (IBAction)yourButtonAction:(id)sender {
     //Action to perform
}
于 2013-03-12T13:06:30.243 回答