在Objective-C中创建匿名委托对象

8
Cocoa广泛使用代理来提供(除其他之外)异步操作的回调方法。然而,我个人不喜欢代理模式以及它如何将非常特定的子操作的处理程序污染到当前类中。UIAlertView是一个完美的例子。
因此,我想知道是否可以通过块简单地创建一个符合代理协议要求(例如UIAlertViewDelegate)的匿名代理对象,并将此匿名对象传递到期望有代理引用的任何位置。
我想象中的代码如下:
id myDelegate = @{
    alertView:alertView didDismissWithButtonIndex:index = ^ {
        ...
    }
};

UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:... message:... delegate:myDelegate cancelButtonTitle:... otherButtonTitles:...;
[alertView show];

我听说Objective-C有一些很好的动态语言特性,但我不知道如何简单地向一个对象添加方法/选择器。这可以相对简单地完成吗?


1
一个月前有一个关于完全通用的代理的问题:https://dev59.com/iG_Xa4cB1Zd3GeqP4LZ4,还有一个关于特定于 UIAlertViewDegate 的旧问题,但我目前找不到它。 - jscs
1
当然,您可以为委托创建完全不同的对象。它不必是您的ViewController。 (但是Objective-C块使我的头爆炸,所以我避免使用它们。) - Hot Licks
1
希望苹果公司能够像在Mac端的NSOpenPanel一样,在UIAlertView等方面添加基于块的API。 - Jon Shier
抱歉,我想到的另一个是UIActionSheet而不是UIAlertView将对象附加到UIActionSheet - jscs
4个回答

5

是的,你提到的语言特性是通过Objective-C运行时公开的,尽管没有内置设施来动态创建委托类,而且运行时API并不友好。

有一个叫做A2DynamicDelegate的库,可以做到你所说的事情。我没有使用过它,但值得调查一下。

编辑:这种方法的问题是代理不会被保留,所以你需要在其他地方保持强引用,或者向UIAlertView添加关联引用。你可能会发现所有这些麻烦都不值得,只需在您的视图控制器中添加一个额外的方法更好(您可以在类扩展中符合委托协议,以避免污染您的接口)。


这里提供了BlocksKit的现代实现 - Cfr

3

一种选项是编写一个类,将委托协议中单个方法的块封装到委托对象中。有关详细信息,请参见此答案


尽管编写一个单独的类来包装块可以帮助分离关注点,但对于本应该非常简单的事情来说,这仍然是很多额外的开销/样板。 - devios1

2
你应该考虑使用一种为UIAlertView添加块支持的类别,这似乎能够满足你的需求。UIAlertView-Blocks是我最喜欢的之一,尽管还有许多其他类别可供选择。

0

如果你想使用基于委托的 API 来使用块,那么你需要进行一些子类化。例如,可以查看PSAlertView,它是 UIAlertView 的子类,提供了基于块的 API。


子类化并不理想。:/ - devios1
3
这不仅不是理想的,而且是被禁止的:UIAlertView类旨在按原样使用,不支持子类化。该类别的视图层次结构是私有的,不得修改。 - vikingosegundo
2
您不需要子类化UIAlertView来添加基于块的API。例如,您可以创建一个名为MyAlert的类,该类拥有一个警报视图,将自身设置为委托,并通过调用客户端代码提供的块来响应委托方法。 - rickster
1
@rickster 这跟BlocksKit做的类似,它很好用。 - Aaron Brager
@rickster 没错。我正在使用类似的方法,代码立即变得更清晰了。 - Sulthan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接