iOS 8 UITableView разделитель 0 не работает

583

У меня есть приложение, где вставка разделителя UITableView установлена ​​на пользовательские значения - Right 0, Left 0. Это отлично работает в iOS 7.x, однако в iOS 8.0 я вижу, что вставка разделителя установлена ​​по умолчанию 15 справа. Хотя в xib файлах он установлен на 0, он все равно отображается неправильно.

Как удалить разделительные поля UITableViewCell?

  • 0
    Вы пытались установить вкладку на 0,001 вместо 0? Я помню, что у меня была похожая проблема, когда вставка края не реагировала на 0, но реагировала на 0,001 (или что-то похожее маленькое).
  • 0
    Я пытался, и это тоже не сработало ..
Показать ещё 2 комментария
Теги:
uitableview
ios8

42 ответа

985
Лучший ответ

iOS 8.0 вводит свойство layoutMargins в ячейках и представлениях таблицы.

Это свойство недоступно в iOS 7.0, поэтому вам нужно убедиться, что вы проверили перед его назначением!

Кроме того, Apple добавила в ячейку свойство , которое не позволит ему наследовать параметры поля "Таблица". Когда это свойство установлено, вашим ячейкам разрешено настраивать собственные поля независимо от вида таблицы. Подумайте об этом как о переопределении.

Это свойство называется preservesSuperviewLayoutMargins, и установка его в NO позволит настройке ячейки layoutMargin переопределить все, что layoutMargin установлено в вашем TableView. Это и экономит время (вам не нужно изменять настройки табличного представления), и более кратким. Пожалуйста, обратитесь к Майку Абдулле за подробным объяснением.

ПРИМЕЧАНИЕ. Следующее - это чистая реализация для параметра уровня ячейки на уровне ячейки, как указано в ответе Майка Абдуллы. Настройка сохраненных ячеекSuperviewLayoutMargins = 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 margin settings
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

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

Настройка свойства preserveesSuperviewLayoutMargins в вашей ячейке на 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];
    }
} 

... и вот ты! Это должно работать на iOS 7 и 8.

РЕДАКТИРОВАТЬ: Мохамед Салех привлек мое внимание к возможному изменению в iOS 9. Вам может потребоваться установить Table View cellLayoutMarginsFollowReadableWidth на NO, если вы хотите для настройки вложений или полей. Ваш пробег может отличаться, это не очень хорошо документировано.

Это свойство существует только в iOS 9, поэтому перед установкой обязательно проверьте.

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

(над кодом из iOS 8 Вставка разделителя UITableView 0 не работает)

EDIT: здесь используется чистый интерфейс Builder:

Изображение 1577 Изображение 1578

ПРИМЕЧАНИЕ. iOS 11 изменяет и упрощает большую часть этого поведения, обновление будет доступно...

  • 2
    Для просмотра таблиц внутри UIPopoverController мне пришлось сделать оба этих действия, как показано выше, а не только в willDisplayCell.
  • 0
    это и мой опыт; вот почему я написал это.
Показать ещё 20 комментариев
260

Arg!!! После того, как вы играете в своем подклассе Cell:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

или установка cell.layoutMargins = UIEdgeInsetsZero; исправила его для меня.

  • 13
    первое решение в этом ответе сработало для меня, второе не сработало.
  • 5
    Не просто используйте cell.layoutMargins = UIEdgeInsetsZero; как это вылетит на iOS 7.x. Лучше проверить, существует ли селектор, прежде чем использовать его. Смотрите мое решение ниже.
Показать ещё 10 комментариев
181

Потратьте минутку, чтобы понять проблему, прежде чем вслепую заряжать ее, чтобы попытаться ее исправить.

Быстрый отскок в отладчике скажет вам, что линии разделителя являются подзонами UITableViewCell. Кажется, что сама ячейка берет на себя большую ответственность за компоновку этих строк.

В iOS 8 вводится понятие макета макета. По умолчанию поля макета вида 8pt со всех сторон, и они наследуются от представлений предков.

Как лучше всего, мы можем сказать, что при выделении его разделительной линии UITableViewCell предпочитает соблюдать левый макет, используя его для ограничения левой вставки.

Объединяя все это, чтобы достичь нужной вставки нулевого нуля, нам необходимо:

  • Установите левый макет разметки на 0
  • Остановить любые наследуемые поля, переопределяющие это

Постарайтесь, это довольно простая задача:

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

Примечания:

  • Этот код нужно запускать только один раз для каждой ячейки (вы все равно настраиваете свойства ячейки), и нет ничего особенного в том, когда вы решите его выполнить. Сделайте то, что кажется вам самым чистым.
  • К сожалению, ни одно свойство не доступно для настройки в Interface Builder, но при желании вы можете указать пользовательский атрибут времени выполнения для preservesSuperviewLayoutMargins.
  • Очевидно, что если ваше приложение также нацелено на более ранние версии ОС, вам нужно будет избежать выполнения вышеуказанного кода до запуска на iOS 8 и выше.
  • Вместо того, чтобы устанавливать preservesSuperviewLayoutMargins, вы можете настроить представления предков (например, таблицу), чтобы иметь также левое поле 0, но это кажется более подверженным ошибкам, поскольку вы не контролируете эту целую иерархию.
  • Возможно, было бы немного чище установить только левое поле на 0 и оставить остальных.
  • Если вы хотите иметь вставки "0" в "дополнительных" разделителях, которые UITableView рисует в нижней части таблиц с обычным стилем, я предполагаю, что потребуется также указать одинаковые настройки на уровне таблицы (не попробовал это!)
  • 3
    Спасибо! Это действительно более краткий ответ. Гораздо лучше, чем переопределять два метода и грубо форсировать его.
  • 2
    Приятно иметь не только как, но и почему. Хорошо структурированный ответ!
Показать ещё 12 комментариев
52

Я считаю, что это тот самый вопрос, который я задал здесь: Удалить SeparatorInset на iOS 8 UITableView для XCode 6 iPhone Simulator

В iOS 8 существует одно новое свойство для всех объектов, наследуемых от UIView. Таким образом, решение установить SeparatorInset в iOS 7.x не сможет удалить пробел, который вы видите в UITableView в iOS 8.

Новое свойство называется " 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

Изображение 1579

Решение: -

-(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];
   }
}

Если вы установите cell.layoutMargins = UIEdgeInsetsZero;, не проверив, существует ли layoutMargins, приложение будет разбиваться на iOS 7.x. Таким образом, лучший способ - проверить, существует ли layoutMargins раньше, чем setLayoutMargins:UIEdgeInsetsZero.

  • 0
    Как можно использовать этот подход, если целью развертывания является iOS 7?
  • 0
    Я поместил код для tableView в viewDidLoad и работает нормально. Я думаю, что нет необходимости вызывать их каждый раз в willDisplayCell ().
44

Вы можете использовать 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 чистым и всегда можете отменить его, если хотите.

  • 2
    Гораздо лучшее из всех решений. Плюс я изучил материал "внешности".
  • 0
    Версия Swift: stackoverflow.com/a/29758091/1431470
39

Быстрая версия

iOS вводит свойство layoutMargins в ячейках и представлениях таблицы.

Это свойство недоступно в iOS 7.0, поэтому вам нужно убедиться, что вы проверите его перед его назначением!

Однако Apple добавила в свою ячейку свойство , называемое preserveesSuperviewLayoutMargins, которое не позволит ему наследовать настройки полей таблицы. Таким образом, ваши ячейки могут настраивать собственные поля независимо от вида таблицы. Подумайте об этом как о переопределении.

Это свойство называется preserveesSuperviewLayoutMargins, а его установка NO может позволить вам переопределить настройки макета таблицы ViewMargin с помощью собственной настройки макета ячейки. Это и экономит время (вам не нужно изменять настройки табличного представления), и более кратким. Пожалуйста, обратитесь к Майку Абдулле за подробным объяснением.

ПРИМЕЧАНИЕ: это правильная, менее запутанная реализация, о чем говорится в ответе Майка Абдуллы; установка сохраненных ячеекSuperviewLayoutMargins = 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 margin settings
    if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
        cell.preservesSuperviewLayoutMargins = false
    }

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

Настройка свойства preserveesSuperviewLayoutMargins в вашей ячейке на 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
    Вам не нужно проверять селекторы в методе willDisplayCell поскольку сам метод уже является iOS 8+ и никогда не будет вызываться из более старых версий.
  • 0
    @ Король-Мастер. Спасибо - это был ответ, который я искал.
Показать ещё 1 комментарий
33

В Swift это немного более раздражает, потому что layoutMargins является свойством, поэтому вам нужно переопределить getter и setter.

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

Это будет эффективно делать layoutMargins только для чтения, что в моем случае это нормально.

  • 0
    Только это решение сработало для меня. И мне не нужно было добавлять дополнительный код строк в свои методы. Я использовал пользовательские ячейки.
  • 1
    Отлично работал для меня в iOS 8 и не падал в iOS 7. Спасибо!
Показать ещё 2 комментария
19

Для iOS 9 вам нужно добавить:

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

Подробнее см. вопрос.

  • 12
    забавно добавлять код для каждой версии, чтобы первоначальный вид оставался прежним ...
18

Расширение 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
  • 0
    ОТЛИЧНО. Люблю все что угодно в расширении :). Спасибо друг.
12

Swift:

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
}
10

Я сделал это, сделав это:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
  • 0
    Огромное спасибо..
8

Пример 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 margin settings
    if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // explicitly setting cell layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}
8

После долгих исследований...

Здесь единственный способ полностью контролировать этот материал (который я мог найти)

Полностью управлять как разделительными вставками, так и макетами на каждой ячейке. Сделайте это в методе willDisplayCell в своем делегате tableview.

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
  • 0
    Единственное решение здесь, которое сработало
8

Для меня простая строка выполняла работу

cell.layoutMargins = UIEdgeInsetsZero
  • 0
    Самый простой (и хороший) ответ.
  • 0
    вызвал это в методе делегата cellForRowAtIndexPath. Хороший ответ :)
8

Что касается предлагаемого cdstamper вместо представления таблицы, добавление ниже строк в методе cellSubview работает для меня.

- (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];
        }
}
7

Простое решение в Swift для iOS 8 с пользовательским UITableViewCell

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

Таким образом вы устанавливаете layoutMargin и separatorInset только один раз вместо того, чтобы делать это для каждого willDisplayCell, как предлагает большинство из приведенных выше ответов.

Если вы используете пользовательский UITableViewCell, это правильное место для этого. В противном случае вы должны сделать это в tableView:cellForRowAtIndexPath.

Еще один намек: вам не нужно устанавливать preservesSuperviewLayoutMargins = false, потому что значение по умолчанию уже NO!

6

Просто добавьте ниже код, который может решить эту программу.

Удачи вам!

-(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];
       }

}
4

Это код, который работает для меня, в 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)
    }
}

Это кажется мне самым чистым (на данный момент), так как все корректировки края/поля ячейки/таблицыView выполняются в методе tableView:willDisplayCell:forRowAtIndexPath:, без переполнения ненужного кода в tableView:cellForRowAtIndexPath:.

Btw, я устанавливаю только ячейку left separatorInset/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
    У меня не работает с iOS 8.1 и Swift.
  • 0
    Что именно у вас не работает? Только что протестировал этот код на симуляторе iPhone 5 с установленным iOS 8.1 SDK, и все так, как было, когда я первоначально опубликовал этот ответ. Код был скомпилирован и запущен с Xcode 6.1.1.
4

Используйте ниже фрагмент кода, чтобы избежать нежелательной проблемы заполнения для UITableView в IOS 8 и 7.

-(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];
    }
}
3

Здесь можно легко удалить глобальную вставку.

В UITableViewCell+Extensions.swift:

import UIKit

extension UITableViewCell {

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

}

В AppDelegate application:didFinishLaunchingWithOptions::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

Вы можете подумать, что a) также просто переопределите separatorInset в расширении, или b) вместо этого установите прокси-сервер внешнего вида для layoutMargins. Ничего не получится. Даже если separatorInset указано как свойство, попытка переопределить его как свойство (или метод) создает ошибки компилятора. И установка прокси-сервера внешнего вида для UITableViewCell layoutMargins (или, если на то пошло, также установка прокси-адресов появления для UITableView layoutMargins и separatorInset) не имеет эффекта.

3

В iOS8:

Добавление этого в мой подкласс UITableViewCell:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

а это "tableView: cellForRowAtIndexPath" или "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

РАБОТАЕТ для меня.

3

Лукас отвечает в Свифте:

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

Вместо обновления preservesSuperviewLayoutMargins и layoutMargins каждый раз, когда ячейка прокручивается (используя 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

}
3

В большинстве ответов показаны разделительные вставки и поля макета, заданные по множеству методов (т.е. viewDidLayoutSubviews, willDisplayCell и т.д.) для ячеек и табличных представлений, но я обнаружил, что просто поместив их в cellForRowAtIndexPath прекрасно работает. Похоже на самый чистый путь.

// 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];
2

Это мое решение. Это относится к пользовательскому подклассу ячеек, просто добавьте их в подкласс.

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

2.

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

И удобно, что вы можете настроить положение разделителя, не прося ваш дизайнер рисовать один для вас..........

2

После просмотра ответов на 3-м этаже я попытался выяснить, какова связь между настройкой разделителя между TableView и TableViewCell и проделана определенная проверка. Вот мои выводы:

  • мы можем считать, что установка разделителя ячеек в нуль должна перемещать разделитель в два этапа: первый шаг - установить ячейку separatorinset на ноль. второй шаг - установить ячейку marginlayout на ноль.

  • установить TableView separatorinset и marginlayout может повлиять на ячейку separatorinset. Однако из теста я обнаружил, что TableView separatorinset кажется бесполезным, TableView marginlayout может реально влиять на ячейку marginlayout.

  • установить Cell PreservesSuperviewLayoutMargins = false, может отключить эффект TableView marginlayout для ячеек.

  • одно из решений:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = UITableViewCell()
    
        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsetsZero
        cell.layoutMargins = UIEdgeInsetsZero
    
        return cell
    }
    
1

Это отлично работало для меня в 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
    Код SWIFT на самом деле является Obj-C. Вероятно, ошибка копирования и вставки;)
1

Добавление этого фрагмента, простой элегантный в Swift работает для меня в iOS8:)

    // tableview single line
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero
}
1

В более компактном виде, чем самый проголосовавший ответ...

- (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];
    }

}

  • 0
    Это, наверное, самый простой и эффективный способ сделать это
1
-(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;
}

Для любой конкретной ячейки вы хотите скрыть разделитель.

0

Для меня никто не работал, кроме этого обходного пути (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

просто поместите эти две строки в метод cellForRowAtIndexPath

  • если вы хотите, чтобы все линии разделителя начинались с нуля [cell setSeparatorInset: UIEdgeInsetsZero]; [cell setLayoutMargins: UIEdgeInsetsZero];

если вы хотите, чтобы конкретная разделительная линия начиналась с нуля, предположим, что последняя строка начинается с нуля

if (indexPath.row == array.count-1) 
{
   [cell setSeparatorInset:UIEdgeInsetsZero];
   [cell setLayoutMargins:UIEdgeInsetsZero];
}
else
   tblView.separatorInset=UIEdgeInsetsMake(0, 10, 0, 0);
0

В Swift вы можете использовать этот

    cell.selectionStyle = UITableViewCellSelectionStyle.None
    cell.preservesSuperviewLayoutMargins = false
    cell.separatorInset = UIEdgeInsetsZero
    cell.layoutMargins = UIEdgeInsetsZero
0

Изображение 1580

использовать раскадровку для изменения вставки разделителя. Пользовательский левый 0 и правый 0, если вы хотите скрыть разделитель на None см. выше изображение

0

Мое решение добавляет UIView как контейнер для подзонов соты. Затем установите ограничения UIView (верхний, нижний, конечный, ведущий) на 0 пунктов. И все ненужные массы уходят. образ, показывающий логику

0

следующий ответ от @cdstamper, лучшим местом является layoutSubviews UITableViewCell, в вашем файле соты (я установил интервал 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)];
        }
    }
0

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
    }
}
0

У меня не было настоящей удачи в любом из вышеперечисленных решений. Я использую файлы NIB для своих табличных ячеек. Я "исправил" это, добавив метку с высотой 1. Я изменил фон ярлыка на черный, привязал ярлык к нижней части наконечника, а затем привязал нижнюю часть остального содержимого к добавленной метке, Теперь у меня черная граница, идущая по дну моих клеток.

Для меня это больше похоже на взлом, но он работает.

Мой единственный выбор - просто полностью исключить границу. Я все еще решаю, буду ли я просто с этим.

0

Я просмотрел все эти замечательные ответы и понял, что большинство из них не работают с 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];
    }
}

Мне не нужно было ничего добавлять. Спасибо всем, кто предоставил ключевые бит.

  • 0
    Спасибо, делать это глобально с внешним видом намного чище.
0

сделайте как мой код:

-(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];
    }
}
-1

С Swift 2.2

создать UITableViewCell extension

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 
}
-1

XCode 7.1 iOS 7, 8, 9:

просто поместите эти две строки в свой TabelViewCell:

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

Это сработало для меня

Ещё вопросы

Сообщество Overcoder
Наверх
Меню