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


662

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

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


Вы пытались установить вкладку на 0,001 вместо 0? Я помню, что у меня была похожая проблема, когда вставка края не реагировала на 0, но реагировала на 0,001 (или что-то похожее маленькое).
Обновление

Я попробовал это, и это тоже не сработало ..
user3570727

4
Тогда я бы предложил установить цвет разделителей [UIColor clearColor]и нарисовать свои собственные разделители. Вы намного более гибки в этом.
Обновление

1
Я до сих пор не могу поверить, что это все еще не одно из UITableViewCellSeparatorStyleзначений по умолчанию. Даже принятый ответ, на мой взгляд, очень грязный взлом.
Энрико Сусатио

Ответы:


1071

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

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

Простое решение - создать подкласс для вашей ячейки и переопределить свойство полей макета, как это предложено @ user3570727. Однако вы потеряете любое поведение системы, например наследование полей из безопасной зоны, поэтому я не рекомендую следующее решение:

(ObjectiveC)

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

(быстрый 4.2):

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

Если вы не хотите переопределять свойство или хотите установить его условно, продолжайте чтение.


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

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

ПРИМЕЧАНИЕ: то, что следует, является чистой реализацией для настройки поля на уровне ячейки , как выражено в ответе Майка Абдуллы. Установка вашей ячейки 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
    }
}

Установка для preservesSuperviewLayoutMarginsсвойства вашей ячейки значения 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 не работает )

РЕДАКТИРОВАТЬ: Вот чистый подход Interface Builder:

TableViewAttributesInspector TableViewCellSizeInspector

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


2
Для просмотра таблиц внутри UIPopoverController мне пришлось сделать оба этих действия, как показано выше, а не только в willDisplayCell.
Чжан

44
Я также обнаружил, что, несмотря на весь вышеприведенный код, который мне все еще приходилось добавлять cell.preservesSuperviewLayoutMargins = NOв соответствии с предложением @ bffmike или после прокрутки способов отображения вставок. (wtf ??)
неорганик

Что если мы хотим установить поле только для одного типа ячеек в сгруппированном tableView?
SAHM

Вы можете попробовать установить его в willDisplayCell и посмотреть, действительно ли это работает (у вас есть дескриптор ячейки, поэтому он должен быть тривиальным). Если это не так, нам нужно сообщить об ошибке. Поля для конкретной ячейки должны быть возможны, IMO.
cdstamper

2
Это сработало для меня с добавлением cell.preservesSuperviewLayoutMarginsв мой источник данных метода:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
МТС

257

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

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

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


13
первое решение в этом ответе сработало для меня, 2-е не сработало.
Spybart

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

3
Он не устанавливает cell.layoutMargins ... Это решение отлично работает, когда у вас уже есть пользовательские ячейки.
Sjoerd исполняет

11
Это будет хорошо работать в iOS 7, так как метод не будет вызван! Вам также нужно установить layoutMargins табличного представления, иначе это не будет работать.
cdstamper

2
переопределение доступа работал для меня. но все остальные решения не сделали. даже настройка separatorInsetв IB не работала. Существует также проблема с цветами фона табличного представления. это действительно больные вещи.
Glasz

178

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

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

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

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

Собрав все это вместе, чтобы достичь желаемой вставки по-настоящему нуля, нам нужно:

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

Скажем так, это довольно простая задача для достижения:

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

Что следует отметить:

  • Этот код нужен только запускать только один раз для каждой ячейки (в конце концов, вы просто настраиваете свойства ячейки), и в этом нет ничего особенного, когда вы решите его выполнить. Делай то, что кажется тебе наиболее чистым.
  • К сожалению, ни одно из свойств не доступно для настройки в Интерфейсном Разработчике, но при желании вы можете указать пользовательский атрибут времени выполнения preservesSuperviewLayoutMargins.
  • Очевидно, что если ваше приложение предназначено и для более ранних выпусков ОС, вам нужно избегать выполнения вышеуказанного кода до тех пор, пока оно не будет запущено на iOS 8 и выше.
  • Вместо установки preservesSuperviewLayoutMargins, вы можете настроить предок представление (например, таблица) , чтобы иметь0 левый край тоже, но это , кажется , по своей природе более подвержены ошибкам , как вы не контролируете , что всю иерархию.
  • Вероятно, было бы немного чище установить только левое поле 0 и оставить остальные.
  • Если вы хотите, чтобы в «лишних» разделителях, которые UITableViewрисуются в нижней части таблиц простых стилей, была вставка 0 , я предполагаю, что для этого потребуется указать те же настройки на уровне таблицы (еще не пробовал!)

3
Спасибо! Это действительно более краткий ответ. Гораздо лучше, чем переопределить два метода и перебрать его.
LunaCodeGirl

16
В iOS 8 для меня это не сработало бы[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
davetw12

1
У вас есть мой голос, спасибо за четкое объяснение. Я просто упомяну, что у самого TableView также есть layoutMargins, которые, возможно, должны быть установлены в дополнение к separatorInset, в некоторых случаях.
cdstamper

@ davetw12 и @cdstamper Можете ли вы предоставить какие-либо доказательства этого? Пока что все мои исследования говорят о том, что установка layoutMarginsи preservesSuperviewLayoutMarginsна ячейку - это все, что требуется. Все остальное похоже на доверие к вуду.
Майк Абдулла

3
Нет, это не форма вуду @MikeAbdullah. Чтобы избежать использования по умолчанию separatorInseta UITableViewCellв iOS 8, вы должны установить значение UIEdgeInsets0 на оба UITableViewи UITableViewCell. Если вы не сделаете оба, у вас все еще будет левый вкладыш, который больше нуля. Я подтвердил это несколько раз.
davetw12

58

Я считаю, что это тот же вопрос, который я задал здесь: удалить 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

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

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


Как можно использовать этот подход, если целью развертывания является iOS 7?
Петар

Я поместил код для tableView в viewDidLoad и работает нормально. Я думаю, что нет необходимости вызывать их каждый раз в willDisplayCell ().
Абдулла Умер

46

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


41

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

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

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

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

ПРИМЕЧАНИЕ: это правильная, менее запутанная реализация, как выражено в ответе Майка Абдуллы; установка preservSuperviewLayoutMargins = 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
    }
}

Если для свойства preservSuperviewLayoutMargins в ячейке установлено значение 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+ и никогда не будет вызываться из более старых версий.
Ривера

38

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

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

Это эффективно сделает layoutMarginsreadonly, что в моем случае хорошо.


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

2
Для статической ячейки, кроме переопределения layoutMargins, вам все равно нужно изменить стиль разделителя ячейки на «Пользовательские вставки» и установить левое значение «0» в раскадровке.
hufeng03

22

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

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

Для более подробной информации, пожалуйста, обратитесь к вопросу .


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

20

Расширение 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

15

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
}

11

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

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;

9

Что касается того, что предложил 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];
        }
}

9

Пример 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
    }
}

9

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

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

Для полного контроля вставок разделителя и полей макета в каждой ячейке. Сделайте это в willDisplayCellметоде на вашем UITableviewDelegate.

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

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

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

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

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

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


8

Для меня простая линия сделала работу

cell.layoutMargins = UIEdgeInsetsZero

вызвал это в методе делегата cellForRowAtIndexPath. Хороший ответ :)
saintjab

7

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

Удачи тебе!

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

}

5

Ответ Лукаша в Свифте:

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

5

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

Кстати, я только устанавливаю левую ячейку 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)
        }
    }

Что именно у вас не работает? Только что протестировал этот код на симуляторе iPhone 5 с установленным iOS 8.1 SDK, и все так, как было, когда я первоначально опубликовал этот ответ. Код был скомпилирован и запущен с Xcode 6.1.1.
Иван

4

Большинство ответов показывает разделительные врезки и макет поля создаются над различными методами (т.е. viewDidLayoutSubviews, willDisplayCellи т.д.) для клеток и tableviews, но я обнаружил , что просто положить их в 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];

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

4

Вместо обновления 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

}

4

Вот простой способ удалить вкладку глобально.

В UITableViewCell+Extensions.swift:

import UIKit

extension UITableViewCell {

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

}

В AppDelegate application:didFinishLaunchingWithOptions::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

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


3

В iOS8:

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

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

и это для "tableView: cellForRowAtIndexPath" или "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

Работал для меня


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

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


2

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

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

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

  3. set PresesSuperviewLayoutMargins = Cell, может обрезать эффект marginlayout TableView на ячейки.

  4. одно из решений:

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

2

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

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

2.

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

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


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

}


1

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

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

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;
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.