我有一个应用程序,其中UITableView的分隔符插入设置为自定义值-右0,左0。这在iOS 7中非常有效。x,但是在iOS 8.0中,我看到右边的分隔符被设置为默认值15。即使在xib文件中它设置为0,它仍然不正确地显示。

如何删除UITableViewCell分隔符边距?


当前回答

我浏览了所有这些精彩的答案,发现其中大多数都不能在iOS 8上运行,或者可以工作,但分隔符在动画期间改变大小,导致不必要的闪烁。这是我在创建窗口之前在我的应用委托中所做的事情:

[[UITableView appearance] setSeparatorInset:UIEdgeInsetsZero];
[[UITableViewCell appearance] setSeparatorInset:UIEdgeInsetsZero];

if ([UITableView instancesRespondToSelector:@selector(setLayoutMargins:)]) {
    [[UITableView appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setPreservesSuperviewLayoutMargins:NO];
}

这是我添加到UITableViewController的:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    }
}

我不需要再添加任何东西了。感谢所有提供关键信息的人。

其他回答

这里有一个简单的方法全局删除嵌入。

在UITableViewCell +移到swift:

import UIKit

extension UITableViewCell {

  override public var layoutMargins: UIEdgeInsets {
    get { return UIEdgeInsetsZero }
    set { }
  }

}

在AppDelegate应用中:didFinishLaunchingWithOptions

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

你可能会想a)也只是覆盖separatorInset在扩展,或b)设置外观代理的layoutmargin,而不是。这两种方法都行不通。即使separatorInset被指示为属性,尝试将其作为属性(或方法)重写也会产生编译器错误。并且为UITableViewCell的layoutmargin设置外观代理(或者,也为UITableView的layoutmargin和separatorInset设置外观代理)没有效果。

而不是每次单元格滚动时更新preservessuperviewlayoutmargin和layoutmargin(使用willDisplayCell),我建议在cellForRowAtIndexPath::

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)

    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero

    return cell

}

iOS在单元格和表视图上引入了layoutmargin属性。

这个属性在iOS 7.0中不可用,所以你需要确保在分配它之前检查!

然而,苹果已经添加了一个名为preservessuperviewlayoutmargin的属性到你的单元格,这将阻止它继承你的表视图的边距设置。这样,单元格可以独立于表视图配置它们自己的边距。把它看作是一个重写。

这个属性叫做preservessuperviewlayoutmargin,将它设置为NO可以让你用你自己单元格的layoutMargin设置来覆盖你的表格视图的layoutMargin设置。它既节省时间(你不必修改表视图的设置),也更简洁。详情请参考Mike Abdullah的回答。

注意:这是正确的,较少混乱的实现,如Mike Abdullah的回答所示;设置你的单元格的preservessuperviewlayoutmargin =NO将确保你的表格视图不会覆盖单元格设置。

第一步-设置单元格边距:

/*
    Tells the delegate that the table view is about to draw a cell for a particular row.
*/
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
    forRowAtIndexPath indexPath: NSIndexPath)
{
    // Remove separator inset
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
        cell.preservesSuperviewLayoutMargins = false
    }

    // Explictly set your cell's layout margins
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }
}

将单元格上的preservessuperviewlayoutmargin属性设置为NO可以防止表视图覆盖单元格边缘。在某些情况下,它似乎不能正常工作。

第二步——只有在所有失败的情况下,你才可以强制使用你的表视图边距:

/*
    Called to notify the view controller that its view has just laid out its subviews.
*/
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Force your tableview margins (this may be a bad idea)
    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }

    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }
}

...好了!这应该可以在iOS 8和iOS 7上运行。

注意:使用iOS 8.1和7.1进行测试,在我的情况下,我只需要使用本解释的第一步。

第二步只需要在渲染的单元格下面有未填充的单元格。如果表的行数大于表模型中的行数。不执行第二步将导致分隔符偏移量不同。

iOS 8及更高版本。Swift 2.0及更高版本:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.separatorInset = UIEdgeInsetsZero
    if #available(iOS 8.0, *) {
        cell.layoutMargins = UIEdgeInsetsZero
    } else {
        // Fallback on earlier versions
    }
}

iOS 8.0在单元格和表视图上引入了layoutmargin属性。

这个属性在iOS 7.0上是不可用的,所以你需要确保你在分配它之前检查!

简单的解决方法是子类化单元格并覆盖@user3570727所建议的layout margin属性。然而,你将失去任何系统行为,如从安全区继承边缘,所以我不建议以下解决方案:

(ObjectiveC)

-(UIEdgeInsets)layoutMargins { 
     return UIEdgeInsetsZero // override any margins inc. safe area
}

迅速(4.2):

override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }

如果不想重写该属性,或者需要有条件地设置它,请继续阅读。


除了layoutmargin属性外,Apple还向单元格添加了一个属性,该属性将阻止单元格继承表视图的边距设置。设置此属性后,允许单元格独立于表视图配置它们自己的边距。把它看作是一个重写。

这个属性叫做preservessuperviewlayoutmargin,将它设置为NO将允许单元格的layoutMargin设置覆盖在TableView上的任何layoutMargin设置。它既节省时间(你不必修改表视图的设置),也更简洁。详情请参考Mike Abdullah的回答。

注意:下面是一个清晰的实现单元格级边缘设置,如Mike Abdullah的回答所示。设置单元格的preservessuperviewlayoutmargin =NO将确保表视图不会覆盖单元格设置。如果你真的想让你的整个表视图有一致的页边距,请相应地调整你的代码。

设置单元格边距:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Remove seperator inset
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

    // Explictly set your cell's layout margins
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

斯威夫特4:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // Remove seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // Prevent the cell from inheriting the Table View's margin settings
    if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // Explictly set your cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

将单元格上的preservessuperviewlayoutmargin属性设置为NO可以防止表视图覆盖单元格边缘。在某些情况下,它似乎不能正常工作。

如果所有这些都失败了,你可以强制你的表视图边距:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    // Force your tableview margins (this may be a bad idea)
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    }
} 

斯威夫特4:

func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Force your tableview margins (this may be a bad idea)
    if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
        tableView.separatorInset = .zero
    }
    if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
        tableView.layoutMargins = .zero
    }
}

...好了!这应该适用于iOS 7和8。


编辑:穆罕默德·萨利赫让我注意到iOS 9中可能发生的变化。你可能需要设置表格视图的cellLayoutMarginsFollowReadableWidth为NO,如果你想自定义插入或边距。您的里程可能会有所不同,这不是很好的记录。

此属性只存在于iOS 9中,所以在设置之前一定要检查。

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
} 

斯威夫特4:

if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
    myTableView.cellLayoutMarginsFollowReadableWidth = false
}

(以上代码来自iOS 8 UITableView分隔符插入0无效)

编辑:这是一个纯接口生成器的方法:

注意:iOS 11改变和简化了很多这种行为,更新即将到来…