Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/41.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 为什么我的表视图单元格在使用reloadRowsAtIndexPaths重新加载时会消失?_Iphone_Objective C_Ios_Uitableview - Fatal编程技术网

Iphone 为什么我的表视图单元格在使用reloadRowsAtIndexPaths重新加载时会消失?

Iphone 为什么我的表视图单元格在使用reloadRowsAtIndexPaths重新加载时会消失?,iphone,objective-c,ios,uitableview,Iphone,Objective C,Ios,Uitableview,我这里有一个简单的示例项目: 在此项目中,UITableView具有自定义UITableViewCell。每个单元格中有3个包含标签的UIView 目标是在点击时使细胞膨胀,然后在再次点击时将其折叠。单元本身必须更改其高度才能显示子视图。不能插入或删除行 演示项目几乎如预期的那样工作。事实上,在iOS 4.3中,它工作得非常完美。然而,在iOS5下,当行崩溃时,前面的单元格神奇地消失了 要重新创建问题,请在具有iOS 5的模拟器或设备中运行项目,然后点击第一个单元格以展开它。然后再次轻敲该单元

我这里有一个简单的示例项目:

在此项目中,UITableView具有自定义UITableViewCell。每个单元格中有3个包含标签的UIView

目标是在点击时使细胞膨胀,然后在再次点击时将其折叠。单元本身必须更改其高度才能显示子视图。不能插入或删除行

演示项目几乎如预期的那样工作。事实上,在iOS 4.3中,它工作得非常完美。然而,在iOS5下,当行崩溃时,前面的单元格神奇地消失了

要重新创建问题,请在具有iOS 5的模拟器或设备中运行项目,然后点击第一个单元格以展开它。然后再次轻敲该单元格以将其折叠。最后,直接点击下方的单元格。前一个消失了

继续敲击该部分中的每个单元格将导致所有单元格消失,直至整个部分丢失

我也尝试过使用重载数据而不是当前的设置,但这会破坏动画,而且感觉有点像黑客。重新加载rowsatindexpaths应该可以工作,但问题是为什么不能呢

请参见下面发生的事情的图片:

下表显示:

单元格展开:

单元格崩溃:

单元格消失(轻敲下方的单元格时):

继续重复,直到整个部分消失:

编辑: 覆盖alpha是一种黑客行为,但有效。这里有另一个“黑客”也能修复它,但为什么它能修复它呢

JVViewController.m第125行:

if( previousIndexPath_ != nil )
{
    if( [previousIndexPath_ compare:indexPath] == NSOrderedSame ) currentCellSameAsPreviousCell = YES;

    JVCell *previousCell = (JVCell*)[self cellForIndexPath:previousIndexPath_];

    BOOL expanded = [previousCell expanded];
    if( expanded )
    {
        [previousCell setExpanded:NO];
        [indicesToReload addObject:[previousIndexPath_ copy]];
    }
    else if( currentCellSameAsPreviousCell )
    {
        [previousCell setExpanded:YES];
        [indicesToReload addObject:[previousIndexPath_ copy]];
    }

    //[indicesToReload addObject:[previousIndexPath_ copy]];
}
编辑2:


对演示项目进行了一些小的更改,值得检查和查看JVViewController的didSelectRowAtIndexPath方法。

我刚刚下载了您的项目,并在使用了
重新加载Rowatindexpath的
didSelectRowAtIndexPath
委托中找到了这段代码

[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView beginUpdates];
[tableView endUpdates];
你为什么不试试这个呢

[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
我之所以建议这样做,是因为我相信,
reloadRowsAtIndexPaths:…
仅在对以下对象的调用之间进行包装时有效:

- (void)beginUpdates;
- (void)endUpdates;
除此之外,行为是未定义的,正如您所发现的,相当不可靠。引用“”的有关部分:

若要为行和节的批量插入和删除设置动画,请在通过连续调用BeginUpdate和EndUpdate定义的动画块中调用插入和删除方法。如果不在此块中调用插入和删除方法,则行和节索引可能无效。BeginUpdate…EndUpdate块不可嵌套

在块结束时,即endUpdates返回后,表视图照常查询其数据源并委托行和节数据。因此,支持表视图的集合对象应该更新以反映新的或删除的行或节

iPhone OS 3.0中引入的ReloadSection:withRowAnimation:和ReloadRowsAndExpaths:withRowAnimation:方法与上面讨论的方法相关。它们允许您请求表视图重新加载特定节和行的数据,而不是通过调用reloadData加载整个可见表视图


可能还有其他合理的原因,但让我仔细考虑一下,因为我也有你的代码,我可以到处乱搞。希望我们能找到答案…

@Javy,我在测试你的应用程序时注意到一些奇怪的行为

iPhone 5.0模拟器上运行时先前的INDExpth_uuu变量为

类NSArray
(看起来像。)以下是调试器输出

 (lldb) po previousIndexPath_
    (NSIndexPath *) $5 = 0x06a67bf0 <__NSArrayI 0x6a67bf0>(

    <JVSectionData: 0x6a61230>,

    <JVSectionData: 0x6a64920>,

    <JVSectionData: 0x6a66260>
    )

    (lldb) po [previousIndexPath_ class]

    (id) $7 = 0x0145cb64 __NSArrayI

你知道这个问题吗?不确定这是否有帮助,但考虑让您知道。

简短而实用的回答:将
UITableViewRowAnimationAutomatic
更改为
UITableViewRowAnimationTop
解决了这个问题。不再有消失的行!(在iOS 5.1上测试)


另一个简短而实用的答案,因为据说UITableViewRowAnimationTop会引起它自己的问题:创建一个新的单元视图,而不是修改现有的框架。在一个真实的应用程序中,单元视图中显示的数据无论如何都应该在应用程序的模型部分,因此,如果设计得当,创建另一个仅以不同方式显示相同数据的单元视图(在本例中为框架)应该不会有问题

有关为同一单元格重新加载设置动画的更多想法:

UITableViewRowAnimationAutomatic
在某些情况下似乎会分解为
UITableViewRowAnimationFade
,即当您看到单元格逐渐消失时。新电池应该淡入,而旧电池应该淡出。但在这里,旧的细胞和新的细胞是一个和相同的-所以,这甚至可以工作吗?在核心动画级别,是否可以淡出视图并同时淡入?听起来可疑。因此,结果就是你只看到淡出。这可能被认为是一个Apple bug,因为预期的行为可能是,如果相同的视图发生了更改,alpha属性将不会被设置动画(因为它不能同时设置为0和1),而是只设置帧、颜色等的动画

请注意,问题只出现在动画的显示中-如果您来回滚动,所有内容都将正确显示

在iOS 4.3中,
自动
模式可能已被解析为除
淡入
之外的其他模式,这就是为什么在那里工作的原因(正如你所写的那样)-我没有深入研究

我不知道为什么iOS会选择淡入淡出模式。但其中一种情况是,当您的代码请求重新加载以前点击的单元格时,该单元格已折叠,并且与当前点击的单元格不同。注意:以前点击的单元格总是被重新加载,代码中的这一行总是被调用:

[indicesToReload addObject:[previousIndexPath_ copy]];
这就解释了失踪的魔力
[indicesToReload addObject:[previousIndexPath_ copy]];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
if( expanded ) {
    [previousCell setExpanded:NO];
    [indicesToReload addObject:[previousIndexPath_ copy]];
}
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationNone];
- (void)setExpanded:(BOOL)expanded
{
    expanded_ = expanded;

    CGFloat newHeight = heightCollapsed_;
    if( expanded_ ) newHeight = heightExpanded_;

    CGRect frame = self.frame;
    frame.size.height = newHeight;
    self.frame = frame;
}
- (void)setExpanded:(BOOL)expanded
{
    expanded_ = expanded;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL currentCellSameAsPreviousCell = NO;
NSMutableArray *indicesToReload = [NSMutableArray array];

if(previousIndexPath_ != nil)
{
    if( [previousIndexPath_ compare:indexPath] == NSOrderedSame ) currentCellSameAsPreviousCell = YES;

    JVCell *previousCell = (JVCell*)[self cellForIndexPath:previousIndexPath_];

    BOOL expanded = [previousCell expanded];
    if(expanded) 
    {
     [previousCell setExpanded:NO];
    }
    else if  (currentCellSameAsPreviousCell)
    {
        [previousCell setExpanded:YES];
    }
    [indicesToReload addObject:[previousIndexPath_ copy]];

    if (expanded)
        previousIndexPath_ = nil;
    else
        previousIndexPath_ = [indexPath copy];         
}

if(currentCellSameAsPreviousCell == NO)
{
    JVCell *currentCell = (JVCell*)[self cellForIndexPath:indexPath];

    BOOL expanded = [currentCell expanded];
    if(expanded) 
    {
        [currentCell setExpanded:NO];
        previousIndexPath_ = nil;
    }

    else
    {
        [currentCell setExpanded:YES];
        previousIndexPath_ = [indexPath copy];
    }

    // moving this line to inside the if statement blocks above instead of outside the loop works, but why?
    [indicesToReload addObject:[indexPath copy]];


}

// commenting out this line makes the animations work, but the table view background is visible between the cells

[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];

// using reloadData completely ruins the animations
[tableView beginUpdates];

 [tableView endUpdates];
}
- (void) refreshTableViewCell:(NSNumber *)row
{
    if (![[NSThread currentThread] isMainThread])
    {
        [self performSelector:_cmd onThread:[NSThread mainThread]  withObject:row waitUntilDone:NO];
        return;
    }

    /*Refresh your cell here
     ...
     */

}
[tableView beginUpdates];
[tableView endUpdates];
    override func tableView(tableView: UITableView,heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if ( indexPath.row == 2){
        resetIndexPath.append(indexPath)
        if resetPassword.on {
            // whatever height you want to set the row to
            return 125
        }
    }
    return 44
}
        @IBAction func resetPasswordSwitch(sender: AnyObject) {

        tableView.reloadData()
        }