【问题标题】:UITableViewCell error ios7UITableViewCell错误ios7
【发布时间】:2013-08-27 21:59:55
【问题描述】:

我有一个问题,我有一个表格,每个单元格中都有一个 UISwitch。当用户单击开关时,我想知道哪个单元格包含开关。

代码在 ios6 和 ios 7 中运行良好:

代码是这样的:

-(IBAction) doToggle:(id)sender {
UISwitch *toggle = (UISwitch *)sender;
MyCell *cell = (MyCell *)((UISwitch *)sender).superview.superview;
NSLog(@"=========== CELL %@", cell.description);
NSDictionary *item = [list objectAtIndex:[cell index]]; //breaks in this line

在 NSLog 中我看到以下内容

iOS6:

<MyCell: 0x858b750; baseClass = UITableViewCell; frame = (0 0; 320 44); autoresize = W; layer = <CALayer: 0x858b890>>

iOS7:

<UITableViewCellScrollView: 0x8e5a290; frame = (0 0; 320 44); autoresize = W+H; gestureRecognizers = <NSArray: 0x8e5a740>; layer = <CALayer: 0x8e5a4c0>; contentOffset: {0, 0}>

谁能帮帮我,在此先感谢!

【问题讨论】:

  • 仅供参考,iOS 7 处于保密协议下,请参阅official Apple developer forums 以获取有关 NDA 下 SDK 的帮助。
  • 谢谢@BergQuester :) 我做到了!
  • 关键是你只能在那里做!
  • 我知道,但这里丰富的意见和建议是无价的;)
  • @BergQuester 仅供参考,NDA 协议不适用于 stackoverflow 用户监管或提升 cmets。

标签: ios objective-c cocoa-touch uitableview ios7


【解决方案1】:

我认为比标签杂耍更清洁的解决方案是使用委托协议创建一个自定义单元格,将方法的目标/操作和单元格添加到 UISwitch 并调用委托(视图控制器)方法-toggleSwitched:(BOOL) switchOnOff onMyCell:(MyCell *) cell,你会实现这个委托方法:

-(void)toggleSwitched:(BOOL) switchOnOff onMyCell:(MyCell *) cell
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    // use indexPath to fetch right element
    // ie:
    if(switchOnOff) {
        NSDictionary *item = list[indexPath.row];
    } else {
        // ??
    }
}

【讨论】:

    【解决方案2】:

    您不应该尝试以这种方式获取数据。如您所见,单元格的结构在 iOS 6 和 iOS 7 中明显不同(我们无法真正谈论,因为 iOS 7 仍处于 NDA 之下)。与其通过“向上爬”子视图路径来获取单元格,不如给你的开关一个等于 indexPath.row 的标签,然后使用它来查询你的数据源以获取字典。

    -(IBAction) doToggle:(UISwitch *)sender {
    
        NSDictionary *item = list[sender.tag];
    } 
    

    【讨论】:

    • 请记住,仅当行是静态的时,使用indexPath.row 作为标记才是有效的选项。如果 UI 允许用户在表中添加、删除或重新排序行,那么切换标签很可能与更新后的行不匹配。这假设您不会在每次插入、删除或移动行后调用 reloadData
    • 使用标签是不好的做法。这比依靠 UITableViewCell 内部遍历视图层次结构要好一些,但是这两种方法都是错误的。您应该使开关 ---> 单元格关系更明确!如果您没有太多单元格,您可以遍历 tableview 的单元格,并将它们的开关与发送者进行比较,直到找到它,但完全面向未来的解决方案是创建一个带有内置开关的自定义单元格(例如 UITableViewCellWithSwitch),并接收来自单元本身的回调,而不是开关。
    • 如果您的表格有多个部分怎么办?
    • @MachOSX,如果你想使用标签,那么你可以使用一些结合了节号和行的数学方程,比如 section*100 +row (当然只有 100 才好,如果你有少于 100 行)。
    【解决方案3】:

    在 iOS7 之前,单元格的超级视图是包含它的 UITableView。从 iOS7 GM 开始(大概也将在公开版本中),单元格的超级视图是 UITableViewWrapperView,其超级视图是 UITableViewCell。该问题有两种解决方案。

    解决方案 #1:创建一个 UITableViewCell 类别

    @implementation UITableViewCell (RelatedTable)
    
    - (UITableView *)relatedTable
    {
        if ([self.superview isKindOfClass:[UITableView class]])
            return (UITableView *)self.superview;
        else if ([self.superview.superview isKindOfClass:[UITableView class]])
            return (UITableView *)self.superview.superview;
        else
        {
            NSAssert(NO, @"UITableView shall always be found.");
            return nil;
        }
    
    }
    @end
    

    这是使用 cell.superview 的一个很好的替代品,可以轻松重构现有代码 -- 只需搜索并替换为 [cell relatedTable],并抛出一个断言以确保如果视图层次结构将来更改或恢复它会立即显示在您的测试中。

    解决方案 #2:添加对 UITableViewCell 的弱 UITableView 引用

    @interface SOUITableViewCell
    
       @property (weak, nonatomic) UITableView *tableView;
    
    @end
    

    这是一个更好的设计,尽管它需要更多的代码重构才能在现有项目中使用。在您的tableView:cellForRowAtIndexPath 中,使用 SOUITableViewCell 作为您的单元格类,或者确保您的自定义单元格类是 SOUITableViewCell 的子类,并将 tableView 分配给单元格的 tableView 属性。在单元格内,您可以使用self.tableView 引用包含的表格视图。

    【讨论】:

      【解决方案4】:

      许多开发人员使用自定义视图在旧版本 iOS 的表格视图中显示自定义单元格。如果您是其中之一,那么您将不得不面对一个问题,即您的按钮单击操作将不再适用于 iOS7。

      如何解决:

      您有三个选择:

      选项 1: 使用新表格单元格创建新布局,而不是查看视图。并将所有布局再次放入表格单元格中。

      我知道,这需要付出很多努力。如果您不想这样做,我们有一个非常小的 hack:选项 2

      选项 2:为您的按钮创建一个 IBOutlet 并将此按钮添加为单元格内容视图的子视图。

      [self.myCell.contentView addSubview:self.btn_click];
      

      上面的代码行将添加 btn_click 作为内容视图的子视图。现在按钮点击动作应该可以工作了。

      选项 3:

      最好的办法:

      i) 取一个插座 UITableViewCell。 ii) 将现有视图作为新表格单元格的子视图。 iii) 断开自定义单元与现有视图的连接,并将其连接到新的 UITableViewCell。

      就是这样,您的 IBAction 现在可以工作了。

      可能是您遇到了 crash 错误消息“class is not key value coding - compliant.”。检查您的旧视图连接并删除所有带有黄色标记的连接。

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题。此代码不保证“(UITableViewCell *)[[[self superview] superview] superview];”。您可以在 iOS7 上使用此代码。

        -(void)buttonClicked:(id)sender
        {
            UIButton *button=(UIButton*)sender;
            UITableViewCell *selectedCell = (UITableViewCell*)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:button.tag inSection:0]];
            NSLog("%@",selectedCell.lblTitle.text);
        }
        

        【讨论】:

          【解决方案6】:

          对于像我这样仍然喜欢简单而肮脏的修复的人,我认为这将解决您的问题!!!干杯!!!!!!

          // Patch to get the table view cell because in iOS7 the superview is a butch
          - (UITableViewCell *) getTableViewCellFromSubview:(UIView*)subview
          {
              UITableViewCell* tableViewCell = nil;
          
              while (subview.superview != Nil) {
                  if ([subview.superview isKindOfClass:[UITableViewCell class]]) {
                      tableViewCell = (UITableViewCell*)subview.superview;
                      break;
                  } else {
                      subview = subview.superview;
                  }
              }
          
              return tableViewCell;
          }
          

          【讨论】:

            【解决方案7】:

            试试这个。它对我有用。

            NSIndexPath *indexPath;
            if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1)
            {
                indexPath = [self.tableview indexPathForCell:(UITableViewCell*)[[senderButton superview] superview]];
            
            }
            else
            {
                indexPath = [self.tableview indexPathForCell:(UITableViewCell*)[[[senderButton superview] superview] superview]];
            }
            
            NSLog(@"table row - %d and table column - %d",indexPath.row , indexPath.section);
            

            【讨论】:

              【解决方案8】:

              当 superview 返回意外对象时,API 已更改导致大量崩溃。下面是我用作自定义 UITableViewCell 的自定义 backgroundView 的自定义 uiview 的 tableview 和单元格访问器的示例。这适用于 ios6/ios7。

              - (UITableView *)tableView
              {
                  if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
                      return (UITableView *)[self cell].superview;
                  } else {
                      // Load resources for iOS 7 or later
                      return (UITableView *)[self cell].superview.superview;
                  }
              
              }
              
              - (UITableViewCell *)cell
              {
                  UIView *v = self;
                  while (v && ![v isKindOfClass:[UITableViewCell class]]) v = v.superview;
                  return (UITableViewCell *)v;
              }
              

              【讨论】:

                【解决方案9】:

                我按照提供的解决方案#1 Answerbot 解决了同样的问题。 (对不起,Answerbot,我还没有足够的声望来投票给你的答案)

                但是,在这种情况下,我们应该创建一个 UIView 类别:

                @implementation UIView (GetCellFromContentviewSubview)
                - (UITableViewCell *)getCellFromContentviewSubview
                {
                    if ([[[self superview] superview] isKindOfClass:[UITableViewCell class]]) {
                        return (UITableViewCell *)[[self superview] superview];
                    }
                    else if ([[[[self superview] superview] superview] isKindOfClass:[UITableViewCell class]]) {
                        return (UITableViewCell *)[[[self superview] superview] superview];
                    }
                    else{
                         NSLog(@"something Panic happens");
                    }
                    return nil;
                }
                
                @end
                

                使用(MyCell *)[mySwitch getCellFromContentviewSubview]替换(MyCell *)[[mySwitch superview] superview],然后,你会得到你的细胞。

                iOS7 的table view cell 的层级好像和iOS6 不一样,在UITableViewCell 和UITableViewCellContentView 之间有一个UITableViewCellScrollView。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-09-26
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-03-07
                  • 1970-01-01
                  • 2014-02-15
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多