2013-03-22 92 views
0

我写了一个自定义类TagsScrollView,它在滚动视图中显示标签。通过多个层次传递委托

当按下标签时,TagsScrollView依赖其委托来实现要执行的操作。几乎所有的时间,这包括:

  1. 更改标签索引移动到另一个指标
  2. 推TagsDetailVC当前的导航控制器。

现在,这是我的应用程序是如何构成的:

enter image description here

虚线表示 “有” 的关系。 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吗?

+3

你有没有考虑使用通知而不是委托? – 2013-03-22 22:49:15

回答

0

你绝对可以做得更好,删除委托模式,使用块。

一个基于块的属性添加到您的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)

+0

嘿,好的答案。所以如果我在TagsScrollView中进行广播,我该如何区分哪个VC会做出反应? MainVC只知道FeedView,而ImageDetailVC直接了解TagsScrollView。 – disappearedng 2013-03-22 23:18:55

+0

mkay,编辑答案 – Eugene 2013-03-22 23:26:31

+0

实际上,我可以递归地检查超级视图,看看它是否是一个特定的VC视图?那应该可以工作 – disappearedng 2013-03-22 23:30:43