重新排序后,iOS 7 UITableView默认分隔符变得怪异

时间:2014-02-13 20:32:28

标签: ios iphone objective-c uitableview

iOS 7中的UITableView上的默认分隔符出现问题。

当用作默认值时,第一个和最后一个分隔符没有插入,其他分隔符有点插入。最初的情况如下:

Everything is OK

一切都好。第一个和最后一个分隔符分布在表格的整个宽度上,而其他分隔符则稍微小一些。现在我将表视图设置为editing,我允许用户重新排序单元格。当用户这样做时,分隔符会搞砸,并且无法正确显示。情况可以在下面的图片中看到:

enter image description here enter image description here

我是否真的需要重新加载数据才能解决此问题,或者它是iOS 7错误还是我做错了什么?

如何解决这个问题?

修改
添加了一些有关我实现的信息。我在NO上发送- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath,在UITableViewCellEditingStyleNone上发送- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath。我的- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath是:

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (!cell)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    cell.shouldIndentWhileEditing = NO;
    cell.textLabel.font = [UIFont someFont];

    UIColor *color = [UIColor randomColor];
    cell.textLabel.text = @"Some text";

    CGRect rect = CGRectMake(0, 0, 15, 15);

    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    [color set];
    CGContextFillEllipseInRect(ctx, rect);

    cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return cell;
}

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    if (sourceIndexPath.row == destinationIndexPath.row) return;

    NSString *tmp = [itemOrder objectAtIndex:sourceIndexPath.row];
    [itemOrder removeObjectAtIndex:sourceIndexPath.row];
    [itemOrder insertObject:tmp atIndex:destinationIndexPath.row];
    didReorder = YES;
}

2 个答案:

答案 0 :(得分:2)

这似乎是iOS SDK中的一个问题。解决它的一种方法是手动将正确的分隔符插入应用于所有单元格。但是,我个人更愿意让系统这样做。

如果在重新排序后重新加载单元格,系统将应用正确的分隔符插入。因此,您应该确保在重新排序后重新加载相关的单元格。

修复用户重新排序

在重新排序(动画)结束后,会在表视图的委托上调用私有方法tableView:didEndReorderingRowAtIndexPath:。在这种方法中,你应该重新加载单元格:

- (void)tableView:(UITableView *)tableView didEndReorderingRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]
                  withRowAnimation:UITableViewRowAnimationNone];
}

此修复仅在行仅在部分内移动(而不在部分之间)时才有效。

(使用方法reloadRowsAtIndexPaths:withRowAnimation:仅在旧位置重新加载移动的单元格和单元格会更有效。但是,您必须在移动单元格之前存储旧位置。实现起来更复杂。对于小部分/简单单元,重新加载整个部分可能会更容易一些。)

修复程序化移动

不幸的是,上一个修补程序中使用的私有委托方法仅在用户重新排序后调用,而不是在以编程方式移动行(使用moveRowAtIndexPath:toIndexPath:)之后调用。因此,我们将不得不使用另一种方法。

从表格视图internally use CALayer animations开始,我们可以使用CATransaction来了解动画何时结束。 (为此,您需要将QuartzCore.framework添加到项目中。)我的修复如下所示:

的UITableView + NicelyMoves.h

#import <UIKit/UIKit.h>

@interface UITableView (NicelyMoves)

- (void)nicelyMoveRowAtIndexPath:(NSIndexPath *)indexPath
                     toIndexPath:(NSIndexPath *)newIndexPath;

@end

的UITableView + NicelyMoves.m

#import <QuartzCore/QuartzCore.h>
#import "UITableView+NicelyMoves.h"

@implementation UITableView (NicelyMoves)

- (void)nicelyMoveRowAtIndexPath:(NSIndexPath *)indexPath
                     toIndexPath:(NSIndexPath *)newIndexPath
{
    [CATransaction begin];

    [CATransaction setCompletionBlock:^{
        // This is executed after the animations have finished
        [self reloadRowsAtIndexPaths:@[indexPath, newIndexPath]
                    withRowAnimation:UITableViewRowAnimationNone];
    }];

    [self moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];

    [CATransaction commit];
}

@end

用法

现在,您应该使用自定义方法moveRowAtIndexPath:toIndexPath:,而不是使用nicelyMoveRowAtIndexPath:toIndexPath:。例如,您可以这样做:

#import "UITableView+NicelyMoves.h"

@implementation YourTableViewController

- (void)moveTheRow
{
    // Move row 0 to 2 in section 0
    NSIndexPath *from = [NSIndexPath indexPathForRow:0 inSection:0];
    NSIndexPath *to = [NSIndexPath indexPathForRow:2 inSection:0];
    [self.tableView nicelyMoveRowAtIndexPath:from toIndexPath:to];
}

@end

答案 1 :(得分:0)

请尝试强制插入尺寸或在viewDidLoad中将其设置为零,以确保tableView尊重它们。

这会将tableView分隔符插件设置为30。

- (void)viewDidLoad {
    [super viewDidLoad];
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 30, 0, 0)];
    }
}

您还可以将特定单元格的分隔符插入设置为:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCellId"];

    if (indexPath.section == 0 && indexPath.row == 0) {
       [cell setSeparatorInset:UIEdgeInsetsMake(0, 30, 0, 0)];
    } else {
       [cell setSeparatorInset:UIEdgeInsetsZero];
    }
    return cell;
}