通过多个层次传递委托
我写了一个自定义类TagsScrollView,它在滚动视图中显示标签。通过多个层次传递委托
当按下标签时,TagsScrollView依赖其委托来实现要执行的操作。几乎所有的时间,这包括:
- 更改标签索引移动到另一个指标
- 推TagsDetailVC当前的导航控制器。
现在,这是我的应用程序是如何构成的:
虚线表示 “有” 的关系。 MainVC有一个FeedView,它有几个FeedCellView,每个FeedCellView又有一个TagsScrollView。
实线表示“推”关系。 ImageDetailVc被压入MainVC的navController。
我该如何组织我的代码,使得TagsScrollView的委托可以优雅地指向MainVC?
现在我已经定义如下:
TagsScrollView.h
@protocol TagPressedDelegate<NSObject>
@required
- (void)tagPressed:(id)sender forQuery:(NSString *)query;
@end
FeedCellView.m
self.tagsScrollView.tagPressedDelegate = self.tagPressedDelegate
FeedView.m
self.cells[0].tagPressedDelegate = self.tagPressedDelegate
MainViewVC.m
self.feed.tagPressedDelegate = self
....
- (void)tagPressed...
我怎样才能避免这种模式?我能做些什么更好?我应该有TagsScrollViewDelegate扩展ScrollViewDelegate吗?
你绝对可以做得更好,删除委托模式,使用块。
一个基于块的属性添加到您的TagsScrollView .h文件中
@property (copy, nonatomic) void (^tagPressedBlock)(id sender, NSString *query);
。M档添加相关的回调
- (void)tagPressed:(id)sender {
if (_tagPressedBlock) {
_tagPressedBlock(sender, self.query); // I'm assuming that the query is your iVar
}
}
分配这样
tagsScrollView.tagPressedBlock = ^(id sender, NSString *query) {
// do stuff with those parameters
}
这对属性“做得更好”
至于如何压制事件代码传递到MainVC
类,你应该使用NSNotificationCenter。
将通知名称定义在全局可见的地方,例如我建议创建一个Defines.h文件并将其包括在Prefix.pch文件中。
无论如何,定义通知名称:
static NSString *const TagPressedNotification = @"TagPressedNotification";
下一步在执行-tagPressed:
发布通知和封装有价值的信息到用户信息词典:
- (void)tagPressed:(id)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:TagPressedNotification object:nil userInfo:@{@"sender" : sender, @"query" : self.query, @"scrollView" : self.tagScrollView}];
//.. code
}
下一页添加MainVC
作为该通知的观察员:
MainVC.m
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(tagPressed:)
name:TagPressedNotification
object:nil];
}
,实施您的MainVC -tagPressed:
方法
- (void)tagPressed:(NSNotification *)notification {
id sender = notification.userInfo[@"sender"];
NSString *query = notification.userInfo[@"query"];
TagScrollView *scrollView = notification.userInfo[@"scrollView"];
if (scrollView == myScrollView) { // the one on your mainVC
// do stuff
}
}
添加,不要忘记清理自己了通知中心的寄存器:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
容易
编辑
我想你也应该传递滚动视图,这是发件人,因为你的mainVC也包含该滚动视图。编辑代码
另一个编辑
创建枚举在Defines.h定义文件
enum {
TagSenderTypeFeed = 1,
TagSenderTypeImageDetail
};
typedef NSInteger TagSenderType;
当创建一个通知加入适当枚举值到您的通知的用户信息字典@"senderType" : @(TagSenderTypeFeed)
嘿,好的答案。所以如果我在TagsScrollView中进行广播,我该如何区分哪个VC会做出反应? MainVC只知道FeedView,而ImageDetailVC直接了解TagsScrollView。 – disappearedng 2013-03-22 23:18:55
mkay,编辑答案 – Eugene 2013-03-22 23:26:31
实际上,我可以递归地检查超级视图,看看它是否是一个特定的VC视图?那应该可以工作 – disappearedng 2013-03-22 23:30:43
你有没有考虑使用通知而不是委托? – 2013-03-22 22:49:15