【问题标题】:Three20 : how to pass a class of objects between 2 viewsThree20:如何在 2 个视图之间传递一类对象
【发布时间】:2011-04-26 08:09:29
【问题描述】:

我有一个 TTableView。此表中的项目映射到一个 url,因此当我单击一个项目时,会出现另一个视图,其中包含有关该项目的信息。 所有这些信息都是类的属性。那么,如何构建我的 TTableTextItem URL 以便将包含信息的类传输到负责显示这些信息的视图?

提前致谢。

【问题讨论】:

    标签: iphone objective-c cocoa three20


    【解决方案1】:

    我几乎没有修复这个很棒的代码 :) 正如发布的版本剥离来自TTTableButton 的回调。

    更正的是:

    if( [object isKindOfClass:[TTTableButton class]] ) {
       if (item.delegate && item.selector) {
           [item.delegate performSelector:item.selector withObject:object];
       }
       [tableView deselectRowAtIndexPath:indexPath animated:YES];
    }
    

    【讨论】:

      【解决方案2】:

      直接使用TTURLAction 的最大问题是您不能真正将它们与TTTableViewItem 一起使用。真正做到这一点的唯一方法是覆盖-didSelectObject:atIndexPath: 并使用query 字典中的所需对象构建您的自定义TTURLAction。但这打破了模型和视图控制器的良好分离,并且一旦您有多个对象要传递,就会变得复杂。

      与此不同,我一直在使用一个小类别,它自动获取表格项的userInfo 属性(我将其设置为我需要的任何内容),并自动将其添加为 URL 参数。

      然后你使用它在你的映射视图控制器中检索它。

      - (id)initWithNavigatorURL:(NSURL *)URL query:(NSDictionary *)query { 
      if (self = [self initWithNibName:nil bundle:nil]) {
          id myPassedObject = [query objectForKey:@"__userInfo__"];
          // do the rest of your initlization
      }
      return self;
      

      }

      您可以将其作为 GitHub Gist here 下载。代码也在下面。我们正在考虑在某个时候将其合并到主分支中。


      TTTableViewDelegate+URLAdditions.h

      @interface TTTableViewDelegate(URLAdditions)
      
      @end
      

      TTTableViewDelegate+URLAdditions.m

      #import "TTTableViewDelegate+URLAdditions.h"
      
      @implementation TTTableViewDelegate(URLAdditions)
      
      - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
          id<TTTableViewDataSource> dataSource = (id<TTTableViewDataSource>)tableView.dataSource;
          id object = [dataSource tableView:tableView objectForRowAtIndexPath:indexPath];
      
          // Added section to automatically wrap up any TTTableItem userInfo objects.  If it is a dictionary, it gets sent directly
          // If it is not, it is put in a dictionary and sent as they __userInfo__ key
          if( [object isKindOfClass:[TTTableLinkedItem class]] ) {
              TTTableLinkedItem* item = object;
      
              if( item.URL && [_controller shouldOpenURL:item.URL] ) {
                  // If the TTTableItem has userInfo, wrap it up and send it along to the URL
                  if( item.userInfo ) {
                      NSDictionary *userInfoDict;
      
                      // If userInfo is a dictionary, pass it along else create a dictionary
                      if( [item.userInfo isKindOfClass:[NSDictionary class]] ) {
                          userInfoDict = item.userInfo;
                      } else {
                          userInfoDict = [NSDictionary dictionaryWithObject:item.userInfo forKey:@"__userInfo__"];
                      }
      
                      [[TTNavigator navigator] openURLAction:[[[TTURLAction actionWithURLPath:item.URL]
                                                               applyQuery:userInfoDict]
                                                              applyAnimated:YES]];
                  } else {
                      TTOpenURL( item.URL );
                  }
              }
      
              if( [object isKindOfClass:[TTTableButton class]] ) {
                  [tableView deselectRowAtIndexPath:indexPath animated:YES];
              }
              else if( [object isKindOfClass:[TTTableMoreButton class]] ) {
                  TTTableMoreButton* moreLink = (TTTableMoreButton*)object;
                  moreLink.isLoading = YES;
                  TTTableMoreButtonCell* cell
                  = (TTTableMoreButtonCell*)[tableView cellForRowAtIndexPath:indexPath];
                  cell.animating = YES;
                  [tableView deselectRowAtIndexPath:indexPath animated:YES];
      
                  if( moreLink.model )
                      [moreLink.model load:TTURLRequestCachePolicyDefault more:YES];
                  else
                      [_controller.model load:TTURLRequestCachePolicyDefault more:YES];
              }
          }
      
          [_controller didSelectObject:object atIndexPath:indexPath];
      }
      
      @end
      

      【讨论】:

        【解决方案3】:

        一种方法是使用 TTURLAction。当用户在您的表中选择一行时,这将调用您的 didSelectObject(TTTableViewController)方法,提取您要传递的对象或对象集并构建一个 TTURLAction,如下所示:

        TTURLAction *action =  [[[TTURLAction actionWithURLPath:@"tt://showUser"] 
            applyQuery:[NSDictionary dictionaryWithObject:user forKey:@"kParameterUser"]]
                    applyAnimated:YES];
        

        然后打开动作:

        [[TTNavigator navigator] openURLAction:action];
        

        您希望通过此操作打开的控制器应该在您的 TTURLMap 中注册,并且应该有一个构造函数:

        - (id) initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
            self = [super init];
            if (self != nil) {
                self.user = [query objectForKey:kParameterUser];
            }
            return self;
        }
        

        我倾向于在类上为我希望能够打开另一个控制器并显示它们自己的对象创建类别。

        【讨论】:

        • 在1.0.5版本中,TTURLAction中没有actionWIthURLPath:applyQuery:的接口,那么如何处理呢?
        • 一点改进 - [query objectForKey:kParameterUser];将是- [query objectForKey:@"kParameterUser"];
        【解决方案4】:

        我认为the documentation on the official website 确实非常清楚地描述了 Three20 的导航方案。您的问题是任何应用程序的常见任务,Three20 对此提供了强大的支持。

        【讨论】:

        • 是的,我已经读过了。但是这个文档很差:它没有解释如何从传递的对象中检索属性,如何在目标视图中访问传递的对象......这就是我卡住的地方。一个例子是受欢迎的。谢谢。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-22
        相关资源
        最近更新 更多