【问题标题】:Trigger a method in UIViewController from its View从其视图触发 UIViewController 中的方法
【发布时间】:2013-02-27 23:25:02
【问题描述】:

我有一个UIViewController,它的UIView 包含一个UIButton。我想在按钮点击事件中触发UIViewController 中的一个方法。
保留UIViewController 的引用似乎不是一个好主意,如下链接所示: Get to UIViewController from UIView?

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

【问题讨论】:

  • 你有你的自定义视图,你把它添加到你的视图控制器中吧?
  • 对..它是我在初始化视图控制器时添加的自定义视图
  • 你可以使用协议来实现这个

标签: ios cocoa-touch uiviewcontroller


【解决方案1】:

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

【讨论】:

  • @ancode:嗯,好的,在这种情况下,我认为你必须使用@selectors。我从来没有这样做过,所以我不记得确切的语法,但我认为这就是它所涉及的。
  • 选择器仅在您引用包含该方法的对象的情况下才起作用.....我没有对该对象的引用:)
【解决方案2】:

在 xCode 中生活很轻松。

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

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

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

【讨论】:

  • 谢谢!但并非在所有情况下都是如此
【解决方案3】:

在 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];

更多信息here

【讨论】:

  • 正如这里所说的self不是目标...self的ViewController是traget
  • @ancode:所以你继承了 UIView,并在那里创建了一个 UIButton?这不是真正的典型方法。当您使用视图控制器创建视图然后将按钮添加为视图的子视图时,是否有特定原因无法创建按钮? (见编辑)
  • 视图可以被很多视图控制器使用!如果我在 ViewController 中添加按钮,那么我必须在所有其他想要相同视图的视图控制器中执行此操作
【解决方案4】:

你可以试试这个:

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

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

- (IBAction)yourButtonAction:(id)sender {
     //Action to perform
}

【讨论】:

    【解决方案5】:

    你可以这样做

    CustomView.h

    #import <UIKit/UIKit.h>
    @protocol CustomViewDelegate <NSObject>
    
     -(void)didButtonPressed;
    
    @end
    
     @interface CustomView : UIView
    
      @property (assign) id<CustomViewDelegate> delegate;
    
    @end
    

    CustomView.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];
    
     }
    

    【讨论】:

    • 这是我一直在寻找的答案.....这是使用委托实现问题中提出的功能的正确方法:)
    • 这比这简单得多,您甚至不需要委托人来做。在下面查看我的答案。
    【解决方案6】:

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

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

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

    • 帮助您分离视图和控制器之间的责任。
    • 保持代码清晰。
    • 让您的代码更加可重用。

    【讨论】:

      【解决方案7】:

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

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-01
        • 1970-01-01
        • 2012-05-14
        • 1970-01-01
        相关资源
        最近更新 更多