代码之家  ›  专栏  ›  技术社区  ›  Peter DeWeese

作为IBaction存储的块关闭

  •  2
  • Peter DeWeese  · 技术社区  · 14 年前

    我试图减少仪式,出于学术上的好奇心,我想知道如何在不使用.m文件中定义的ibaction方法的情况下执行以下操作,以便在发生接口生成器有线操作(如按钮按下)时使用闭包。你可以说我想暗示下面的cancelButtonPress方法,而不是必须定义它。一个uiviewcontroller子类或者某个类别中存储的一些魔力是可以接受的。

    @interface MyViewController : UIViewController
    {
        void(^doOnCancel)(void);
    }
    
    @property (nonatomic, copy) void(^doOnCancel)(void);
    
    - (IBAction)cancelButtonPress:(id)sender;//I want this gone!
    
    @end
    

    我试图改变 void IBAction 在属性和变量中没有运气。

    编辑: 另一种模式也可以减少在操作中使用闭包的重复性。

    赏金是为了一个好的模式,允许闭包以一种可以用来减少仪式的方式被任意地用于服务ib中定义的操作。到目前为止,“不能做”的评论可能正确,也可能不正确。

    3 回复  |  直到 14 年前
        1
  •  3
  •   Jens Ayton    14 年前

    这里是一个允许任何块类型属性用作操作的黑客程序: http://gist.github.com/589740

    正如你所说,这是学术上的好奇心。我真的不建议在reals上使用它。

    此外,它并不能严格满足您的要求,因为该操作是在未实现的类别中声明的。这纯粹是为了让接口生成器可以通过扫描头文件自动找到它。您可以删除它并在IBS检查器中手动添加该操作,但这对我来说似乎是一个损失,因为以这种方式保持同步很难。

        2
  •  4
  •   mohsenr    14 年前

    Ahruman的方法很好,但它可能过于依赖运行时。除性能问题外,还包括旋转和使用 initialize 如果其他人想同时使用运行时,则更容易受到bug的影响。我建议使用C宏。

    在类的顶部(或任何地方,真的)定义这些宏:

    typedef void(^BlockAction)(id sender);
    #define BlockActionProperty(ACTION)     @property (copy) BlockAction ACTION;\
                                            - (IBAction) ACTION:(id)sender;
    
    #define BlockActionSynthesize(ACTION)   @synthesize ACTION;\
                                            - (IBAction) ACTION:(id)sender {\
                                                if (ACTION) ACTION(sender);\
                                            }
    

    现在要创建一个新操作,只需替换 @property ... 在标题中包含以下内容(例如):

    BlockActionProperty(testAction);
    

    并在实施过程中通过以下方式“综合”IT:

    BlockActionSynthesize(testAction);
    

    在任何时候,如果您想要覆盖它并使用普通的操作方法,您所需要做的就是像往常一样合成和实现该操作。

    这比运行时更快(在我看来更干净),而且 IBAction 定义的接口生成器可以“查看”其定义。

        3
  •  1
  •   Chuck    14 年前

    不必诉诸于“把通常会出现的代码放在 cancelButtonPress: 在里面 forwardInvocation: 不能。接口生成器操作发送消息。调用块不能是操作消息的直接结果。

    扩展一个控件是可能的,这样它就可以调用一个块,而不是向控制器发送一个普通的操作方法,但这将需要更多的代码,而且它不会神奇地使接口生成器支持它。