iOS 8 UITableView 分隔符插图 0 不起作用

iOS 8 UITableView separator inset 0 not working

提问人:user3570727 提问时间:9/11/2014 最后编辑:Shobhakar Tiwariuser3570727 更新时间:4/30/2020 访问量:187485

问:

我有一个应用程序,其中的分隔符插图设置为自定义值 - 右、左。这在 中完美工作,但是在我看到分隔符插图设置为右侧的默认值。即使在它设置为 的 xib 文件中,它仍然显示不正确。UITableView00iOS 7.xiOS 8.0150

如何删除分隔页边距?UITableViewCell

iOS 的Objective-C Swift UITableView iOS8

评论

0赞 freshking 9/11/2014
您是否尝试过将插图设置为 0.001 而不是 0?我记得遇到过类似的问题,边缘插图不会对 0 做出反应,但对 0.001(或类似的小东西)有反应。
0赞 user3570727 9/11/2014
我试过了,也没有用。
4赞 freshking 9/11/2014
然后,我建议将分隔符颜色设置为并绘制自己的分隔符。这样你就更灵活了。[UIColor clearColor]
2赞 Enrico Susatyo 12/18/2014
我仍然不敢相信这仍然不是默认值之一。在我看来,即使是公认的答案也是一个非常肮脏的黑客。UITableViewCellSeparatorStyle

答:

260赞 user3570727 9/11/2014 #1

精 氨 酸!!!在玩完之后,在你的子类中这样做:Cell

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

或为我设置修复它。cell.layoutMargins = UIEdgeInsetsZero;

评论

13赞 spybart 9/11/2014
这个答案中的第一个解决方案对我有用,第二个解决方案不起作用。
5赞 Ricky 9/11/2014
不要只使用 cell.layoutMargins = UIEdgeInsetsZero;因为它会在 iOS 7.x 上崩溃。最好在使用之前先检查选择器是否存在。请参阅下面的解决方案。
3赞 Sjoerd Perfors 9/16/2014
他没有设置 cell.layoutMargins ...当您已经有自定义单元格时,此解决方案非常有效。
11赞 emma ray 9/17/2014
这在 iOS 7 中可以正常工作,因为该方法不会被调用!但是,您还需要设置表视图的 layoutMargins,否则它将不起作用。
2赞 glasz 9/22/2014
覆盖访问器对我有用。但所有其他解决方案都没有。 甚至在IB中配置也不起作用。表视图背景颜色也存在问题。这真是恶心的东西。separatorInset
39赞 swilliams 9/11/2014 #2

在 Swift 中,它稍微烦人一些,因为它是一个属性,所以你必须覆盖 getter setter。layoutMargins

override var layoutMargins: UIEdgeInsets {
  get { return UIEdgeInsetsZero }
  set(newVal) {}
}

这将有效地使只读,这在我的情况下很好。layoutMargins

评论

0赞 Ramis 10/1/2014
只有这个解决方案对我有用。而且我不需要在方法中添加额外的行代码。我确实使用了自定义单元格。
2赞 hufeng03 11/4/2014
对于静态单元格,除了覆盖 layoutMargins 之外,您仍然需要将单元格的分隔符样式更改为“自定义插图”,并在情节提要中将左值设置为“0”。
60赞 Ricky 9/11/2014 #3

我相信这与我在这里提出的问题相同: 删除 iOS 8 UITableView for XCode 6 iPhone 模拟器上的 SeparatorInset

iOS 8 中,继承自 的所有对象都有一个新属性。因此,在 iOS 7.x 中设置 的解决方案将无法删除您在 iOS 8 的 UITableView 上看到的空白。UIViewSeparatorInset

新属性称为“layoutMargins”。

@property(nonatomic) UIEdgeInsets layoutMargins
Description   The default spacing to use when laying out content in the view.
Availability  iOS (8.0 and later)
Declared In   UIView.h
Reference UIView Class Reference

iOS 8 UITableView setSeparatorInset:UIEdgeInsetsZero setLayoutMargins:UIEdgeInsetsZero

解决方案:-

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

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

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

   if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
   }
}

如果在未检查是否存在的情况下进行设置,则应用程序将在 iOS 7.x 上崩溃。因此,最好的方法是先检查是否存在。cell.layoutMargins = UIEdgeInsetsZero;layoutMarginslayoutMarginssetLayoutMargins:UIEdgeInsetsZero

评论

0赞 Petar 12/3/2014
如果部署目标设置为 iOS 7,如何使用此方法?
0赞 Abdullah Umer 1/19/2015
我将tableView的代码放在viewDidLoad中并且工作正常。我认为没有必要每次都在willDisplayCell()中调用它们。
1077赞 emma ray 9/17/2014 #4

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

此属性在 iOS 7.0 上不可用,因此您需要确保在分配它之前进行检查!

简单的解决方法是按照@user3570727的建议对单元格进行子类化并覆盖布局边距属性。但是,您将失去任何系统行为,例如从安全区域继承边距,因此我不建议使用以下解决方案:

(目标C)

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

(斯威夫特 4.2):

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

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


除了该属性之外,Apple 还向单元格添加了一个属性,该属性将阻止它继承“表视图”的边距设置。设置此属性后,允许单元格独立于表格视图配置自己的边距。将其视为覆盖。layoutMargins

此属性称为 ,如果将其设置为 ,则允许单元格的设置覆盖 TableView 上设置的任何内容。它既节省了时间(您不必修改表视图的设置),又更简洁。请参考迈克·阿卜杜拉(Mike Abdullah)的回答以获取详细说明。preservesSuperviewLayoutMarginsNOlayoutMarginlayoutMargin

注意:以下是单元格级边距设置的干净实现,如 Mike Abdullah 的回答中所表达的那样。设置单元格的 preservesSuperviewLayoutMargins=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
    }
}

将单元格上的属性设置为 NO 防止表视图覆盖单元格边距。在某些情况下,它似乎无法正常工作。preservesSuperviewLayoutMargins

如果全部失败,您可以暴力破解表视图边距:

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


编辑:穆罕默德·萨利赫(Mohamed Saleh)引起了我的注意,iOS 9中可能发生了一些变化。如果要自定义插图或边距,则可能需要将“表格视图”设置为。您的里程可能会有所不同,这没有很好的记录。cellLayoutMarginsFollowReadableWidthNO

此属性仅存在于 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 中的以上代码不起作用)

编辑:这是一个纯粹的Interface Builder方法:

TableViewAttributesInspector TableViewCellSizeInspector

注意:iOS 11更改并简化了大部分此行为,更新即将推出...

评论

2赞 Zhang 9/21/2014
对于 UIPopoverController 中的表视图,我必须执行如上所示的这两个操作,而不仅仅是在 willDisplayCell 中执行。
44赞 inorganik 9/23/2014
我还发现,尽管上面有所有代码,但我仍然必须按照@bffmike的建议添加,或者在滚动插图的出现方式后添加。(WTF??)cell.preservesSuperviewLayoutMargins = NO
0赞 SAHM 10/7/2014
如果我们只想为分组 tableView 中的一种类型的单元格设置边距怎么办?
2赞 mts 10/11/2014
这在我的数据源方法中添加了以下功能,对我有用:cell.preservesSuperviewLayoutMargins- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
1赞 SAHM 10/26/2017
您是否碰巧有iOS 11的此答案的更新?它不再起作用。
10赞 Vijay V S 9/26/2014 #5

至于 cdstamper 建议而不是表格视图,在单元格的 layoutSubview 方法中添加以下行对我有用。

- (void)layoutSubviews 
{
    [super layoutSubviews];

    if ([self respondsToSelector:@selector(setSeparatorInset:)])
                [self setSeparatorInset:UIEdgeInsetsZero];

        if ([self respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)])
        {
            [self setPreservesSuperviewLayoutMargins:NO];;
        }

        if ([self respondsToSelector:@selector(setLayoutMargins:)]) 
        {
            [self setLayoutMargins:UIEdgeInsetsZero];
        }
}
16赞 Alexander Volkov 10/22/2014 #6

迅速:

override func viewDidLoad() {
    super.viewDidLoad()

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

    self.tableView.layoutIfNeeded()            // <--- this do the magic
}

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

    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }

    return cell
}
5赞 inorganik 10/30/2014 #7

大多数答案都显示了在单元格和表格视图的各种方法(即 、 、 等)上设置的分隔符插图和布局边距,但我发现将它们放入效果很好。似乎是最干净的方式。viewDidLayoutSubviewswillDisplayCellcellForRowAtIndexPath

// kill insets for iOS 8
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) {
    cell.preservesSuperviewLayoutMargins = NO;
    [cell setLayoutMargins:UIEdgeInsetsZero];
}
// iOS 7 and later
if ([cell respondsToSelector:@selector(setSeparatorInset:)])
    [cell setSeparatorInset:UIEdgeInsetsZero];
5赞 Anooj VM 11/3/2014 #8

使用以下代码片段避免IOS 8和7中UITableView不必要的填充问题。

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

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

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

    if ([cell respondsToSelector:@selector(setLayoutMargins:)])
    {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}
6赞 Ivan 11/4/2014 #9

这是在 Swift 中对我有用的代码:

override func viewDidLoad() 
{
    super.viewDidLoad()
    ...
    if tableView.respondsToSelector("setSeparatorInset:") {
        tableView.separatorInset = UIEdgeInsetsZero
    }
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath)
{
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset.left = CGFloat(0.0)
    }
    if tableView.respondsToSelector("setLayoutMargins:") {
        tableView.layoutMargins = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins.left = CGFloat(0.0)
    }
}

这对我来说似乎是最干净的(目前),因为所有 cell/tableView 边缘/边距调整都是在方法中完成的,而不会将不必要的代码塞入 .tableView:willDisplayCell:forRowAtIndexPath:tableView:cellForRowAtIndexPath:

顺便说一句,我只设置单元格的左分隔符Inset/layoutMargins,因为在这种情况下,我不想搞砸我在单元格中设置的约束。

代码更新到 Swift 2.2:

 override func viewDidLoad() {
   super.viewDidLoad()       

    if tableView.respondsToSelector(Selector("setSeparatorInset:")) {
      tableView.separatorInset = UIEdgeInsetsZero
        }
    }

 override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
        if cell.respondsToSelector(Selector("setSeparatorInset:")) {
            cell.separatorInset.left = CGFloat(0.0)
        }
        if tableView.respondsToSelector(Selector("setLayoutMargins:")) {
            tableView.layoutMargins = UIEdgeInsetsZero
        }
        if cell.respondsToSelector(Selector("setLayoutMargins:")) {
            cell.layoutMargins.left = CGFloat(0.0)
        }
    }

评论

0赞 Ivan 1/2/2015
究竟什么对你不起作用?刚刚在安装了 iOS 8.1 SDK 的 iPhone 5 模拟器上测试了这段代码,一切都和我最初发布这个答案时一样。代码是用 Xcode 6.1.1 编译和运行的。
180赞 Mike Abdullah 11/9/2014 #10

让我们花点时间了解这个问题,然后再盲目地冲进去尝试解决问题。

在调试器中快速浏览一下就会发现分隔线是 的子视图。似乎单元本身对这些线的布局负有相当大的责任。UITableViewCell

iOS 8 引入了布局边距的概念。默认情况下,视图的布局边距位于所有边,并且它们继承自祖先视图。8pt

据我们所知,在布置其分隔线时,选择尊重左侧布局边距,用它来约束左侧插图。UITableViewCell

综上所述,要实现所需的真正零点,我们需要:

  • 将左侧布局边距设置为0
  • 停止任何继承的边距覆盖该边距

这样说来,这是一个非常简单的任务:

cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;

注意事项:

  • 此代码只需要在每个单元运行一次(毕竟您只是配置单元格的属性),并且当您选择执行它时并没有什么特别之处。做你觉得最干净的事情。
  • 遗憾的是,这两个属性都无法在Interface Builder中配置,但如果需要,您可以指定用户定义的运行时属性。preservesSuperviewLayoutMargins
  • 显然,如果您的应用也面向早期的操作系统版本,则需要避免执行上述代码,直到在 iOS 8 及更高版本上运行。
  • 您可以将祖先视图(例如表)配置为也具有左边距,而不是设置 ,但这本身似乎更容易出错,因为您无法控制整个层次结构。preservesSuperviewLayoutMargins0
  • 只设置左边距并保留其他边距可能会稍微干净一些。0
  • 如果您想在纯样式表格底部绘制的“额外”分隔符上插入 0,我猜这也需要在表格级别指定相同的设置(没有尝试过这个!UITableView

评论

3赞 LunaCodeGirl 11/14/2014
谢谢!这确实是更简洁的答案。比覆盖两种方法并暴力破解要好得多。
16赞 davetw12 12/6/2014
在 iOS 8 中,对我来说,如果没有[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
1赞 emma ray 12/7/2014
你有我的投票,谢谢你的明确解释。我只想提一下,在某些情况下,除了 separatorInset 之外,TableView 本身还具有 layoutMargins,可能需要设置这些 layoutMargins。
0赞 Mike Abdullah 12/8/2014
@davetw12和@cdstamper 你能提供任何证据吗?到目前为止,我的所有探索都表明,只需要在单元格上设置和设置即可。其他任何事情都感觉像是相信巫毒教。layoutMarginspreservesSuperviewLayoutMargins
3赞 davetw12 12/9/2014
不,这不是巫毒教@MikeAbdullah的一种形式。为了避免在 iOS 8 中出现默认值 a,您必须将 set the 设置为零 和 .如果不同时执行这两项操作,则仍将有一个大于零的左边插图。我已经多次确认了这一点。separatorInsetUITableViewCellUIEdgeInsetsUITableViewUITableViewCell
5赞 Rudolf Adamkovič 12/1/2014 #11

而不是更新和每次单元格滚动(使用 ),我建议在以下位置进行一次:preservesSuperviewLayoutMarginslayoutMarginswillDisplayCellcellForRowAtIndexPath:

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

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

    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero

    return cell

}
42赞 King-Wizard 12/24/2014 #12

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

此属性在 iOS 7.0 中不可用,因此您需要确保在分配它之前进行检查!

但是,Apple 已将一个名为 preservesSuperviewLayoutMargins 的属性添加到单元格中,该属性将阻止它继承表视图的边距设置。这样,单元格就可以独立于表格视图配置自己的边距。将其视为覆盖。

此属性称为 preservesSuperviewLayoutMargins,将其设置为 NO 可以允许您使用自己的单元格的 layoutMargin 设置覆盖表视图的 layoutMargin 设置。它既节省了时间(您不必修改表视图的设置),又更简洁。请参考迈克·阿卜杜拉(Mike Abdullah)的回答以获取详细说明。

注意:这是适当的、不那么混乱的实现,正如迈克·阿卜杜拉的回答所表达的那样;设置单元格的 preservesSuperviewLayoutMargins=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
    }
}

将单元格的 preservesSuperviewLayoutMargins 属性设置为 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 进行测试,就我而言,我只需要使用本说明的第一步。

仅当呈现的单元格下方有未填充的单元格时,才需要执行第二步,即。如果表大于表模型中的行数。不执行第二步将导致不同的分隔符偏移。

评论

1赞 E. Rivera 6/15/2015
您无需检查方法中的选择器,因为该方法本身已经是 iOS 8+,并且永远不会从旧版本调用。willDisplayCell
0赞 Bkillnest 12/24/2014 #13

让我们按照我的代码做:

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

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

    if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        cell.preservesSuperviewLayoutMargins = NO;
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]){
        [cell setSeparatorInset:UIEdgeInsetsZero];
    }
}
12赞 ideawu 12/30/2014 #14

我通过这样做使它工作:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
47赞 Lukasz 2/3/2015 #15

可以在应用程序启动时(在加载 UI 之前)使用 UIAppearance 一次,将其设置为默认全局设置:

// iOS 7:
[[UITableView appearance] setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[[UITableView appearance] setSeparatorInset:UIEdgeInsetsZero];

[[UITableViewCell appearance] setSeparatorInset:UIEdgeInsetsZero];

// iOS 8:
if ([UITableView instancesRespondToSelector:@selector(setLayoutMargins:)]) {

    [[UITableView appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setPreservesSuperviewLayoutMargins:NO];

}

这样,您可以保持 UIViewController 的代码干净,并且始终可以根据需要重写它。

0赞 spstanley 2/27/2015 #16

我浏览了所有这些精彩的答案,并意识到它们中的大多数都不适用于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];
    }
}

我不需要添加任何其他内容。感谢所有提供关键部分的人。

3赞 xmurobi 3/6/2015 #17
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        // ... Get the cell
        cell.separatorInset = UIEdgeInsetsMake(0.f, 20.f, 0.f, [UIScreen mainScreen].bounds.size.width - 20);
        // others
        return cell;
}

对于要隐藏分隔符的任何特定单元格。

6赞 Naka 4/21/2015 #18

Lukasz 在 Swift 中的回答:

    // iOS 7:
    UITableView.appearance().separatorStyle = .SingleLine
    UITableView.appearance().separatorInset = UIEdgeInsetsZero
    UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

    // iOS 8:
    if UITableView.instancesRespondToSelector("setLayoutMargins:") {
        UITableView.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().preservesSuperviewLayoutMargins = false
    }
9赞 Francesco Vadicamo 6/4/2015 #19

Swift for iOS 8 中的简单解决方案,带有自定义UITableViewCell

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

通过这种方式,您只设置一次,而不是像上面大多数答案所建议的那样对每次都进行设置。layoutMarginseparatorInsetwillDisplayCell

如果您使用的是自定义,这是执行此操作的正确位置。 否则,您应该在 .UITableViewCelltableView:cellForRowAtIndexPath

再提示一下:你不需要设置,因为默认值已经是!preservesSuperviewLayoutMargins = falseNO

1赞 subharb 6/9/2015 #20

以比得票最多的答案更紧凑的方式......

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    if ([cell respondsToSelector:@selector(setSeparatorInset:)] && [cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)] && [cell respondsToSelector:@selector(setLayoutMargins:)]) {
         [cell setSeparatorInset:UIEdgeInsetsZero];
         [cell setPreservesSuperviewLayoutMargins:NO];
         [cell setLayoutMargins:UIEdgeInsetsZero];
    }

}

5赞 Saru 6/10/2015 #21

在 iOS8 中:

将其添加到我的 UITableViewCell 子类中:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

并将其转换为“tableView:cellForRowAtIndexPath”或“tableView:willDisplayCell”:

[editCell setSeparatorInset:UIEdgeInsetsZero];

为我工作。

0赞 Scott 6/22/2015 #22

我对上述任何解决方案都没有任何真正的运气。我正在将 NIB 文件用于我的表格单元格。我通过添加一个高度为 1 的标签来“修复”这个问题。我将标签的背景更改为黑色,将标签固定在笔尖的底部,然后将其余内容的底部固定到添加的标签上。现在我的细胞底部有一个黑色边框。

对我来说,这感觉更像是一种黑客攻击,但它确实有效。

我唯一的其他选择就是完全消除边界。我还在决定我是否要这样做。

0赞 Zia 6/30/2015 #23

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
    }
}
3赞 Xin Chen 8/29/2015 #24

在看到 3 楼的答案后,我试图弄清楚在 TableView 和 TableViewCell 之间设置分隔符的关系,并做了一些测试。以下是我的结论:

  1. 我们可以认为将单元格的分隔符设置为零必须分两步移动分隔符:第一步是将单元格的分隔符设置为零。第二步是将单元格的 marginlayout 设置为零。

  2. 设置 TableView 的 separatorinset 和 marginlayout 可能会影响 Cell 的 separatorinset但是,从测试中,我发现 TableView 的分隔符似乎毫无用处,TableView 的 marginlayout 实际上会影响单元格的 marginlayout

  3. set Cell's PreservesSuperviewLayoutMargins = false,可以切断 TableView 对 Cells 的 marginlayout 影响。

  4. 解决方案之一:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = UITableViewCell()
    
        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsetsZero
        cell.layoutMargins = UIEdgeInsetsZero
    
        return cell
    }
    
1赞 ddnl 9/2/2015 #25

添加这个片段,在 Swift 中简单优雅,在 iOS8 中对我有用:)

    // tableview single line
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero
}
3赞 Guoyu 9/9/2015 #26

这是我的解决方案。这适用于自定义单元格子类,只需将它们都添加到子类中即可。

  1. - (UIEdgeInsets)layoutMargins {    
        return UIEdgeInsetsMake(0, 10, 0, 10);
    }
    

2.

self.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);

而且很方便,您可以自定义分隔符的位置,而无需让您的设计师为您绘制一个..........

21赞 Dan Beaulieu 9/10/2015 #27

Swift 2.0 扩展

我只是想分享一个我所做的扩展,以从表视图单元格分隔符中删除边距。

extension UITableViewCell {
    func removeMargins() {

        if self.respondsToSelector("setSeparatorInset:") {
            self.separatorInset = UIEdgeInsetsZero
        }

        if self.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
            self.preservesSuperviewLayoutMargins = false
        }

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

在上下文中使用:

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

    cell.removeMargins()
    return cell
24赞 Julian 9/30/2015 #28

对于iOS 9,您需要添加:

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

详情请参阅问题

评论

12赞 Christian 10/3/2015
为每个版本添加一些代码以使初始外观保持不变很有趣......
1赞 jithin 10/3/2015 #29

这在 iOS 8 和 iOS 9 中对我来说非常有效。

对于OBJ-C

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  { 
        if ([tableView respondsToSelector:@selector(setSeparatorInset:)])
        {
            [tableView setSeparatorInset:UIEdgeInsetsZero];
        }

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

        if ([cell respondsToSelector:@selector(setLayoutMargins:)])
        {
            [cell setLayoutMargins:UIEdgeInsetsZero];
        }
         return cell;
    }
0赞 BollMose 10/21/2015 #30

根据@cdstamper的回答,更好的地方是UITableViewCell的layoutSubviews,在你的单元格文件中(我设置了1%的间距,你可以设置为零),所以只需要在这里设置代码来处理所有情况(旋转和其他):

 -(void)layoutSubviews
    {
        [super layoutSubviews];
        if ([self respondsToSelector:@selector(setSeparatorInset:)]) {
            [self setSeparatorInset:UIEdgeInsetsMake(0,self.bounds.size.width*0.01,0,self.bounds.size.width*0.01)];
        }
        if ([self respondsToSelector:@selector(setLayoutMargins:)]) {
            [self setLayoutMargins:UIEdgeInsetsMake(0,self.bounds.size.width*0.01,0,self.bounds.size.width*0.01)];
        }
    }
4赞 Scott Gardner 10/23/2015 #31

这是全局删除插图的简单方法。

在:UITableViewCell+Extensions.swift

import UIKit

extension UITableViewCell {

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

}

在:AppDelegateapplication:didFinishLaunchingWithOptions:

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

您可能会想 a) 也只是在扩展中覆盖,或者 b) 将外观代理设置为 。两者都行不通。即使被指示为属性,尝试将其作为属性(或方法)重写也会生成编译器错误。为 ' 设置外观代理(或者,就此而言,也为 's 和 设置外观代理)不起作用。separatorInsetlayoutMarginsseparatorInsetUITableViewCelllayoutMarginsUITableViewlayoutMarginsseparatorInset

-1赞 Te Be 11/2/2015 #32

XCode 7.1 iOS 7、8、9:

只需将以下两行放在 TabelViewCell 中:

    self.layoutMargins = UIEdgeInsetsZero;
    self.preservesSuperviewLayoutMargins = false;

这对我有用

0赞 Akif 12/30/2015 #33

我的解决方案是将 UIView 添加为单元格子视图的容器。然后将此 UIView 约束(顶部、底部、尾随、前导)设置为 0 磅。所有不必要的质量都消失了。显示逻辑的图像

9赞 apinho 2/18/2016 #34

对我来说,简单的线条就完成了工作

cell.layoutMargins = UIEdgeInsetsZero

评论

0赞 saintjab 5/30/2016
在 cellForRowAtIndexPath 委托方法中调用此函数。好答案:)
0赞 Phani Sai 3/28/2016 #35

enter image description here

使用情节提要更改分隔符插入自定义左 0 和右 0, 如果要将分隔符隐藏为“无” 见上图

-1赞 swiftBoy 4/12/2016 #36

使用 Swift 2.2

创建 UITableViewCell 扩展

import UIKit

extension UITableViewCell {
    func removeMargins() {

        if self.respondsToSelector(Selector("setSeparatorInset:")) {
            self.separatorInset = UIEdgeInsetsZero
        }

        if self.respondsToSelector(Selector("setPreservesSuperviewLayoutMargins:")) {
            self.preservesSuperviewLayoutMargins = false
        }

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

现在,您可以在 cellForRowAtIndex 中使用

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
            cell.removeMargins()//To remove seprator inset 
}
0赞 Anny 6/22/2016 #37

在 Swift 中,你可以使用它

    cell.selectionStyle = UITableViewCellSelectionStyle.None
    cell.preservesSuperviewLayoutMargins = false
    cell.separatorInset = UIEdgeInsetsZero
    cell.layoutMargins = UIEdgeInsetsZero
10赞 Matjan 7/5/2016 #38

经过大量调查...

这是完全控制这些东西的唯一方法(我能找到的)

完全控制每个单元格上的分隔符插图和布局边距。在 .willDisplayCellUITableviewDelegate

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.layoutMargins = UIEdgeInsetsZero
    cell.contentView.layoutMargins = UIEdgeInsetsMake(0, 10, 0, 10)
    cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
}

单元格对象控制分隔符,而其他所有内容则控制。如果您的分隔符插入空间以意外的颜色显示,这应该可以解决它:contentView

cell.backgroundColor = cell.contentView.backgroundColor
8赞 JimmyChang 7/15/2016 #39

只需添加以下代码即可解决此程序。

祝你好运!

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

       if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
       }

       if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
           [cell setLayoutMargins:UIEdgeInsetsZero];
       }

}
10赞 mkz 8/18/2016 #40

Swift 3.0 示例:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // removing seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // prevent the cell from inheriting the tableView's margin settings
    if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // explicitly setting cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}
0赞 Shabnam 9/29/2016 #41

只需将这两行放在 cellForRowAtIndexPath 方法中即可

  • 如果要将所有分隔线都从零开始 [单元格集SeparatorInset:UIEdgeInsetsZero]; [单元格 setLayoutMargins:UIEdgeInsetsZero];

如果要 特定的分隔线从零开始,假设这里是最后一行从零开始

if (indexPath.row == array.count-1) 
{
   [cell setSeparatorInset:UIEdgeInsetsZero];
   [cell setLayoutMargins:UIEdgeInsetsZero];
}
else
   tblView.separatorInset=UIEdgeInsetsMake(0, 10, 0, 0);
0赞 Daniele Ceglia 12/1/2016 #42

对我来说,除了这个解决方法(Swift 3.0)之外,没有一个有效:

extension UIColor {
    static func colorWith(hex:String, alpha: CGFloat) -> UIColor {
        var cString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()

        if cString.hasPrefix("#") {
            cString.remove(at: cString.startIndex)
        }

        if cString.characters.count != 6 {
            return UIColor.gray
        }

        var rgbValue:UInt32 = 0
        Scanner(string: cString).scanHexInt32(&rgbValue)

        return UIColor(red:   CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
                       green: CGFloat((rgbValue & 0x00FF00) >> 8)  / 255.0,
                       blue:  CGFloat( rgbValue & 0x0000FF)        / 255.0,
                       alpha: alpha)
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdendifier, for: indexPath)

    cell.backgroundColor = UIColor.colorWith(hex: "c8c7cc", alpha: 1) // same color of line separator

    return cell
}
0赞 MDalprato 9/25/2018 #43

只需覆盖“cellForRowAtIndexPath”并设置“cell.preservesSuperviewLayoutMargins = false”和“cell.separatorInset = UIEdgeInsets.zero”和“cell.layoutMargins = UIEdgeInsets.zero”

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell: LayoutTableViewCell! = tableView.dequeueReusableCell(withIdentifier: "LayoutCell") as? LayoutTableViewCell



    let currentLayout = OrderLayouts()[indexPath.row]

    cell.NameLabel?.text = currentLayout.name
    cell.DescrLabel?.text = currentLayout.descr

    if(GlobalVariables.debug){

        cell.DescrLabel?.text = "\(currentLayout.id) \n \(currentLayout.descr)"

    }

    cell.preservesSuperviewLayoutMargins = false
    cell.separatorInset = UIEdgeInsets.zero
    cell.layoutMargins = UIEdgeInsets.zero


    return cell

}