简体   繁体   English

UITableViewCell错误iOS7

[英]UITableViewCell error ios7

I have a problem, I have a table and in each cell a UISwitch. 我有一个问题,我有一个表,每个单元中都有一个UISwitch。 When the user clicks the switch I would like to know which cell contained the switch. 当用户单击开关时,我想知道哪个单元格包含开关。

The code is working fine in ios6 and in ios 7 breaks: 该代码在ios6和ios 7中断中运行良好:

The code is like this: 代码是这样的:

-(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

In the NSLog I see the following 在NSLog中,我看到以下内容

iOS6: iOS6:

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

iOS7: IOS 7:

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

Can some one help me with this, Thanks in advance! 有人可以帮助我吗,谢谢!

I think a much cleaner solution than the tag juggling would be to create a custom cell with a delegate protocol, add a target/action of the method and the cell to the UISwitch and call on the delegate (the view controller) the method -toggleSwitched:(BOOL) switchOnOff onMyCell:(MyCell *) cell and you would implement this delegate method something like: 我认为比标记变戏法更干净的解决方案是使用委托协议创建自定义单元格,将方法的目标/动作和单元格添加到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 {
        // ??
    }
}

You shouldn't be trying to get your data this way. 您不应该尝试以这种方式获取数据。 As you see, the structure of the cell is apparently different in iOS 6 and iOS 7 (which we can't really talk about since iOS 7 is still under NDA). 如您所见,该单元的结构在iOS 6和iOS 7中显然有所不同(由于iOS 7仍在NDA之下,因此我们不能真正谈论它们)。 Rather than getting the cell by "climbing up" the subview path, give your switch a tag equal to the indexPath.row, and then use that to query your data source to get the dictionary. 与其通过“爬上”子视图路径来获取单元格,不如给开关一个等于indexPath.row的标记,然后使用该标记来查询数据源以获取字典。

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

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

Before iOS7, the cell's superview was the UITableView that contained it. 在iOS7之前,单元的超级视图是包含它的UITableView As of iOS7 GM (so presumably will be in the public release as well) the cell's superview is a UITableViewWrapperView with its superview being the UITableViewCell . 从iOS7 GM开始(大概也将在公共发行版中),单元的超级视图为UITableViewWrapperView ,其超级视图为UITableViewCell There are two solutions to the problem. 有两种解决方案。

Solution #1: Create a UITableViewCell category 解决方案#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

This is a good drop-in replacement to using cell.superview , makes it easy to refactor your existing code -- -- just search and replace with [cell relatedTable] , and throws in an assert to ensure that if the view hierarchy changes or reverts in the future it will show up immediately in your tests. 这是使用cell.superview一个很好的直接替代品,可以轻松地重构您的现有代码-只需搜索并替换为[cell relatedTable] ,并抛出一个断言以确保视图层次结构是否更改或将来还原,它将立即显示在您的测试中。

Solution #2: Add a Weak UITableView reference to UITableViewCell 解决方案2:将弱的UITableView引用添加到UITableViewCell

@interface SOUITableViewCell

   @property (weak, nonatomic) UITableView *tableView;

@end

This is a much better design, though it will require a bit more code refactoring to use in existing projects. 这是一个更好的设计,尽管需要更多的代码重构才能在现有项目中使用。 In your tableView:cellForRowAtIndexPath use SOUITableViewCell as your cell class or make sure your custom cell class is subclassed from SOUITableViewCell and assign the tableView to the cell's tableView property. tableView:cellForRowAtIndexPath将SOUITableViewCell用作单元格类,或确保自定义单元格类是从SOUITableViewCell ,并将tableView分配给单元格的tableView属性。 Inside the cell you can then refer to the containing tableview using self.tableView . 然后,您可以在单元格内部使用self.tableView引用包含的tableview。

Many of the developer used custom view to show custom cell on Table view for older version of iOS. 许多开发人员使用自定义视图在旧版iOS的“表”视图上显示自定义单元格。 If you are one of them, then you will have to face a problem that your button click action will no longer work with iOS7. 如果您是其中之一,那么您将面临一个问题,即您的按钮单击操作将不再适用于iOS7。

How to resolve this: 如何解决这个问题:

You have three options: 您有三种选择:

Option 1: Create the new lay out with new table cell instead of taking view. 选项1:使用新表格单元格而不是视图来创建新布局。 and put all layouts again in table cell. 并将所有布局再次放在表格单元格中。

I know, this will require a lot of effort. 我知道,这将需要很多努力。 If you don't want to do this, we have a very small hack for it : option 2 如果您不想这样做,我们可以做一个很小的修改:选项2

Option 2: Create a IBOutlet for your button and add this button as a subview of your cell's content view. 选项2:为按钮创建IBOutlet,并将此按钮添加为单元格内容视图的子视图。

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

The above line of code will add btn_click as a subview of you content view. 上面的代码行将btn_click添加为内容视图的子视图。 Now button click action should work. 现在,按钮单击动作应该起作用。

Option 3: 选项3:

The best way : 最好的方法 :

i) Take An outlet UITableViewCell. i)取一个插座UITableViewCell。 ii) Make existing view as subview of new table cell. ii)将现有视图作为新表单元的子视图。 iii) Disconnect the connection of custom cell to existing view and connect it to new UITableViewCell. iii)断开自定义单元与现有视图的连接,并将其连接至新的UITableViewCell。

thats it, Your IBAction will work now. 就是这样,您的IBAction现在可以工作了。

May be you got the crash with error message that " class is not key value coding - compliant .". 可能是您崩溃,并显示错误消息“ 类不符合键值编码标准 。”。 Check your old view connection and remove all connection having yellow mark. 检查您的旧视图连接,并删除所有带有黄色标记的连接。

I got the same problem. 我遇到了同样的问题。 this code is not guaranteed " (UITableViewCell *)[[[self superview] superview] superview]; ". 此代码不保证“ (UITableViewCell *)[[[self superview] superview] superview]; ”。 You can this code working on iOS7. 您可以在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);
}

For those people who still like simple and dirty fixes like me i think this will solve your problem!!! 对于那些仍然喜欢像我这样简单而肮脏的修复程序的人,我认为这将解决您的问题!!! cheers!!!!! 干杯!!!!!

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

Try this out.It works for me. 试试看。它对我有用。

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

The API has changed causing a lot of crashes when superview returns unexpected objects. 当Superview返回意外对象时,API已更改,导致大量崩溃。 Below is an example of tableview and cell accessors for a custom uiview i'm using as a custom backgroundView for my custom UITableViewCell. 下面是自定义uiview的tableview和单元格访问器的示例,我将其用作自定义UITableViewCell的自定义backgroundView。 This works with both ios6/ios7. 这适用于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;
}

I solved the same problem by following the solution#1 Answerbot provided. 我通过遵循提供的solution#1 Answerbot解决了相同的问题。 (Sorry, Answerbot, I don't have enough reputation yet to vote up your answer) (对不起,Answerbot,我没有足够的声誉来投票赞成你的答案)

However, in this case, we should creat a UIView category: 但是,在这种情况下,我们应该创建一个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

Use (MyCell *)[mySwitch getCellFromContentviewSubview] replace (MyCell *)[[mySwitch superview] superview] , then, you will get your cell. 使用(MyCell *)[mySwitch getCellFromContentviewSubview]替换(MyCell *)[[mySwitch superview] superview] ,您将获得单元格。

It seems that the table view cell's hierarchy in iOS7 is different from iOS6, there's a UITableViewCellScrollView between UITableViewCell and UITableViewCellContentView. 似乎iOS7中的表格视图单元格的层次结构与iOS6不同,UITableViewCell和UITableViewCellContentView之间有一个UITableViewCellScrollView。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM