UITableViewCell错误ios7

时间:2013-08-27 21:59:56

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

我有一个问题,我有一张桌子,每个单元格都有一个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}>

有人可以帮助我,提前谢谢!

9 个答案:

答案 0 :(得分:4)

我认为比标签杂耍更清晰的解决方案是创建具有委托协议的自定义单元格,将方法和单元格的目标/操作添加到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 {
        // ??
    }
}

答案 1 :(得分:2)

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

-(IBAction) doToggle:(UISwitch *)sender {

    NSDictionary *item = list[sender.tag];
} 

答案 2 :(得分:2)

在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:向UITableView

添加弱UITableViewCell引用
@interface SOUITableViewCell

   @property (weak, nonatomic) UITableView *tableView;

@end

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

答案 3 :(得分:1)

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

如何解决此问题:

您有三种选择:

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

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

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

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

上面的代码行将添加btn_click作为内容视图的子视图。现在按钮点击操作应该有效。

选项3:

最好的方法:

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

就是这样,你的IBAction现在可以使用了。

您可能会遇到崩溃,并显示错误消息“类不符合键值编码。”。检查旧视图连接并删除所有带黄色标记的连接。

答案 4 :(得分:1)

我遇到了同样的问题。此代码无法保证“(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);
}

答案 5 :(得分:1)

对于那些仍然喜欢像我这样的简单和肮脏修复的人,我认为这将解决你的问题!欢呼声!!!!!

// 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;
}

答案 6 :(得分:1)

试试这个。它对我有用。

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);

答案 7 :(得分:0)

当superview返回意外对象时,API已更改导致大量崩溃。下面是一个自定义uiview的tableview和单元格访问器示例,我将其用作自定义UITableViewCell的自定义backgroundView。这适用于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;
}

答案 8 :(得分:0)

我按照提供的#1 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中的表视图单元格的层次结构与iOS6不同,UITableViewCell和UITableViewCellContentView之间存在UITableViewCellScrollView。