Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 通过多层次结构传递委托_Iphone_Objective C - Fatal编程技术网

Iphone 通过多层次结构传递委托

Iphone 通过多层次结构传递委托,iphone,objective-c,Iphone,Objective C,我编写了一个自定义类TagsScrollView,它在滚动视图中显示标记 当按下标记时,TagsScrollView依赖其委托来执行操作。几乎所有时候,这都涉及: 将选项卡索引更改为其他索引 将TagsDetailVC按到当前导航控制器 现在,这就是我的应用程序的结构: 虚线表示“有”关系。MainVC有一个FeedView,它有几个FeedCellView,每个FeedCellView又有一个TagsScrollView 实线表示“推送”关系。ImageDetailVc被推送到MainVC的

我编写了一个自定义类TagsScrollView,它在滚动视图中显示标记

当按下标记时,TagsScrollView依赖其委托来执行操作。几乎所有时候,这都涉及:

  • 将选项卡索引更改为其他索引
  • 将TagsDetailVC按到当前导航控制器 现在,这就是我的应用程序的结构:

    虚线表示“有”关系。MainVC有一个FeedView,它有几个FeedCellView,每个FeedCellView又有一个TagsScrollView

    实线表示“推送”关系。ImageDetailVc被推送到MainVC的导航控制器上

    如何组织代码,使TagsScrollView的委托可以优雅地指向MainVC

    现在,我定义了以下内容:

    TagsScrollView.h

    @protocol TagPressedDelegate<NSObject>
    @required
    - (void)tagPressed:(id)sender forQuery:(NSString *)query;
    @end
    

    如何避免这种模式?我能做得更好吗?我应该改为使用标记ScrollViewDelegate扩展ScrollViewDelegate吗

    您肯定可以做得更好,删除委派模式,使用块

    将基于块的属性添加到TagsScrollView.h文件中

    @property(复制,非原子)void(^tagPressedBlock)(id发送者,NSString*查询)

    在.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文件中

    无论如何,请定义通知名称:

    静态NSString*const TagPressedNotification=@“TagPressedNotification”

    下一步在执行
    -tagPressed:
    时发布该通知,并将有价值的信息封装到userInfo字典中:

    - (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
      }
    }
    
    添加不要忘记将自己从NotificationCenter的注册表中清除:

    - (void)dealloc {
      [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    轻松的

    编辑

    我想您还应该传递scroll视图,它是发送方,因为mainVC也包含该滚动视图。编辑代码

    另一次编辑

    在Defines.h文件中创建枚举define

    enum {
      TagSenderTypeFeed = 1,
      TagSenderTypeImageDetail
    };
    typedef NSInteger TagSenderType;
    

    在创建通知时,将适当的枚举值添加到通知的userInfo字典
    @“senderType”:@(TagSenderTypeFeed)

    您考虑过使用通知而不是委托吗?回答得好。因此,如果我在TagsScrollView中进行广播,我如何区分哪个VC会做出反应?MainVC只知道FeedView,ImageDetailVC直接知道TagsScrollView。实际上,我可以递归地检查superview,看看它是否是特定VC的视图吗?这应该可以工作,这比我建议的更糟,不要偷懒,用正确的方法。问题是我的tagsScrollView不知道枚举类型是什么,因为我不总是能够直接指定它。在我的图表中,只有ImageDetailVC可以这样做。MainVC堆栈上的TagsScrollView无法知道这一点,除非MainVC通过多层让它知道这一点,这与我以前遇到的tagsPressedElegate模式类似。@tc。啊。。。有时,讽刺性的评论会产生非常多的积极影响。。。我现在知道了如何正确使用积木,以及如何避免保留循环。。。谢谢你,伙计
    enum {
      TagSenderTypeFeed = 1,
      TagSenderTypeImageDetail
    };
    typedef NSInteger TagSenderType;