Inserção 0 do separador UITableView do iOS 8 não está funcionando

662

Eu tenho um aplicativo em que a UITableViewinserção do separador está definida como valores personalizados - Direita 0, Esquerda 0. Isso funciona perfeitamente iOS 7.x, no entanto, iOS 8.0vejo que a inserção do separador está definida como o padrão 15à direita. Mesmo que nos arquivos xib ele tenha definido como0 , ele ainda aparece incorretamente.

Como removo as UITableViewCellmargens do separador?

user3570727
fonte
Você já tentou definir a inserção como 0,001 em vez de 0? Lembro-me de ter um problema semelhante em que a inserção da borda não reagiria a 0, mas reagiria a 0,001 (ou algo semelhante pequeno).
freshking 10/09/14
Eu tentei isso e não quer trabalhar ..
user3570727
4
Então eu sugiro definir a cor dos separadores [UIColor clearColor]e desenhar seus próprios separadores. Você é muito mais flexível assim.
freshking 10/09/14
1
Ainda não acredito que esse ainda não seja um dos UITableViewCellSeparatorStylepadrões. Até a resposta aceita é um truque muito sujo na minha opinião.
Enrico Susatyo

Respostas:

1071

O iOS 8.0 apresenta a propriedade layoutMargins nas células E nas visualizações de tabela.

Esta propriedade não está disponível no iOS 7.0, portanto, verifique antes de atribuí-la!

A solução fácil é subclassificar sua célula e substituir a propriedade das margens do layout, conforme sugerido por @ user3570727. No entanto, você perderá qualquer comportamento do sistema, como herdar margens da Área segura, por isso não recomendo a solução abaixo:

(Objetivo C)

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

(rápido 4.2):

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

Se você não deseja substituir a propriedade ou precisa configurá-la condicionalmente, continue lendo.


Além da layoutMarginspropriedade, a Apple adicionou uma propriedade ao seu celular que impedirá que ela herde as configurações de margem do seu Table View. Quando essa propriedade é configurada, suas células têm permissão para configurar suas próprias margens, independentemente da exibição da tabela. Pense nisso como uma substituição.

Essa propriedade é chamada preservesSuperviewLayoutMarginse a configuração para NOpermitirá que a layoutMarginconfiguração da célula substitua o que layoutMarginestiver definido no seu TableView. Isso economiza tempo ( você não precisa modificar as configurações da Visualização da tabela ) e é mais conciso. Consulte a resposta de Mike Abdullah para obter uma explicação detalhada.

NOTA: o que se segue é uma implementação limpa para uma configuração de margem no nível da célula , conforme expresso na resposta de Mike Abdullah. A configuração de sua célula preservesSuperviewLayoutMargins=NOgarantirá que a Visualização da tabela não substitua as configurações da célula. Se você realmente deseja que toda a exibição da tabela tenha margens consistentes, ajuste seu código de acordo.

Configure as margens da sua célula:

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

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

Definir a preservesSuperviewLayoutMarginspropriedade em sua célula como NÃO deve impedir que a exibição da tabela substitua as margens da célula. Em alguns casos, parece não funcionar corretamente.

Se tudo falhar, você pode forçar com força suas margens do Table View:

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

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

... e lá vai você! Isso deve funcionar no iOS 7 e 8.


EDIT: Mohamed Saleh me chamou a atenção para uma possível alteração no iOS 9. Você pode precisar definir as Table View cellLayoutMarginsFollowReadableWidthcomoNO se você deseja personalizar inserções ou margens. Sua milhagem pode variar, isso não está muito bem documentado.

Esta propriedade existe apenas no iOS 9, portanto, verifique antes de configurar.

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

Swift 4:

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

(o código acima da inserção 0 do separador UITableView do iOS 8 não está funcionando )

EDIT: Aqui está uma abordagem pura do Interface Builder:

TableViewAttributesInspector TableViewCellSizeInspector

OBSERVAÇÃO: o iOS 11 muda e simplifica muito desse comportamento, uma atualização será lançada ...

cdstamper
fonte
2
Para visualizações de tablaturas dentro de um UIPopoverController, eu tive que fazer os dois como mostrado acima, em vez de apenas no willDisplayCell.
Zhang
44
Eu também descobri que, apesar de todo o código acima, eu ainda tinha que adicionar cell.preservesSuperviewLayoutMargins = NOa sugestão de @ bffmike ou depois de rolar as maneiras pelas quais as inserções apareceriam. (wtf ??)
inorganik
E se quisermos definir a margem apenas para um tipo de célula em um tableView agrupado?
SAHM
Você pode tentar configurá-lo no willDisplayCell e ver se isso realmente funciona (você tem um identificador na célula, portanto deve ser trivial). Caso contrário, precisamos registrar um bug. As margens de layout específicas da célula devem ser possíveis, IMO.
Cdstamper
2
Isso funcionou para mim com a adição de cell.preservesSuperviewLayoutMarginsno meu método de fonte de dados:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
mts
257

Arg !!! Depois de brincar, faça isso na sua Cellsubclasse:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

ou definindo o cell.layoutMargins = UIEdgeInsetsZero;fixo para mim.

user3570727
fonte
13
a primeira solução nesta resposta funcionou para mim, a segunda não funcionou.
Spybart 10/09/14
5
Não basta usar cell.layoutMargins = UIEdgeInsetsZero; pois ele trava no iOS 7.x. É melhor verificar se o seletor existe primeiro antes de usá-lo. Veja minha solução abaixo.
Ricky
3
Ele não está definindo cell.layoutMargins ... Essa solução funciona muito bem quando você já possui células personalizadas.
Sjoerd Perfors
11
Isso funcionará bem no iOS 7, pois o método não será chamado! Você também precisa definir o layoutMargins da exibição da tabela, ou ele não funcionará.
Cdstamper 16/09/14
2
substituir o acessador funcionou para mim. mas todas as outras soluções não. mesmo configurando o separatorInsetno IB não funcionou. também há um problema com as cores de fundo da exibição de tabela. isso é coisa realmente doentia.
glasz
178

Vamos tirar um momento para entender o problema antes de carregar cegamente para tentar corrigi-lo.

Uma rápida olhada no depurador lhe dirá que as linhas separadoras são subvisões de UITableViewCell . Parece que a própria célula assume uma grande quantidade de responsabilidade pelo layout dessas linhas.

O iOS 8 apresenta o conceito de margens de layout . Por padrão, as margens do layout de uma vista são 8ptde todos os lados e são herdadas das visualizações de ancestral.

O melhor que podemos dizer é que, ao estabelecer sua linha separadora, UITableViewCell escolhe respeitar a margem do layout esquerdo, usando-a para restringir a inserção esquerda.

Juntando tudo isso, para alcançar a inserção desejada de zero, precisamos:

  • Defina a margem esquerda do layout como 0
  • Interrompa as margens herdadas substituindo

Em outras palavras, é uma tarefa bem simples de se conseguir:

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

Coisas a serem observadas:

  • Esse código precisa apenas ser executado uma vez por célula (você está apenas configurando as propriedades da célula), e não há nada de especial em quando você escolhe executá-lo. Faça o que lhe parecer mais limpo.
  • Infelizmente, nenhuma propriedade está disponível para configuração no Interface Builder, mas é possível especificar um atributo de tempo de execução definido pelo usuário, preservesSuperviewLayoutMarginsse desejado.
  • Claramente, se o seu aplicativo também tiver como destino versões anteriores do sistema operacional, você precisará evitar a execução do código acima até executar no iOS 8 e superior.
  • Em vez de definir preservesSuperviewLayoutMargins, você pode configurar as visualizações de ancestrais (como a tabela) para terem 0margem esquerda também, mas isso parece inerentemente mais propenso a erros, pois você não controla toda a hierarquia.
  • Provavelmente seria um pouco mais limpo definir apenas a margem esquerda 0e deixar as outras.
  • Se você deseja inserir 0 nos separadores "extras" que UITableViewdesenham na parte inferior das tabelas de estilo simples, acho que será necessário especificar também as mesmas configurações no nível da tabela (ainda não tentei essa!)
Mike Abdullah
fonte
3
Obrigado! Esta é realmente a resposta mais concisa. Muito melhor do que substituir dois métodos e forçar brutalmente.
LunaCodeGirl
16
Em iOS 8, para mim, isso não iria funcionar sem[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
davetw12
1
Você tem meu voto, obrigado pela explicação clara. Mencionarei apenas que o TableView em si também possui layoutMargins que pode precisar ser definido além do separatorInset, em alguns casos.
Cddamper
@ davetw12 e @cdstamper Você pode fornecer alguma evidência disso? Até agora, todas as minhas explorações dizem que é necessário definir tanto na célula layoutMarginsquanto preservesSuperviewLayoutMarginsna célula. Qualquer outra coisa parece confiar no vodu.
Mike Abdullah
3
Não, não é uma forma de vodu @ MikeAbdullah. Para evitar o padrão separatorInsetde a UITableViewCellno iOS 8, você deve definir o conjunto UIEdgeInsetscomo zero no UITableViewe no UITableViewCell. Se você não fizer as duas coisas, ainda terá uma inserção esquerda maior que zero. Eu confirmei isso várias vezes.
precisa saber é o seguinte
58

Acredito que esta seja a mesma pergunta que fiz aqui: Remover SeparatorInset no iOS 8 UITableView for XCode 6 iPhone Simulator

No iOS 8 , há uma nova propriedade para todos os objetos herdados UIView. Portanto, a solução para definir oSeparatorInset iOS 7.x não poderá remover o espaço em branco que você vê no UITableView no iOS 8.

A nova propriedade é chamada " 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

A solução:-

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

Se você definir cell.layoutMargins = UIEdgeInsetsZero;sem verificar se layoutMarginsexiste, o aplicativo falhará no iOS 7.x. Portanto, a melhor maneira seria verificar se o layoutMarginsprimeiro existe antes setLayoutMargins:UIEdgeInsetsZero.

Ricky
fonte
Como essa abordagem pode ser usada se o destino de implantação estiver definido no iOS 7?
Petar
Coloquei o código para tableView em viewDidLoad e estou funcionando bem. Eu acho que não é necessário chamá-los sempre em willDisplayCell ().
Abdullah Umer
46

Você pode usar UIAppearance uma vez, na inicialização do aplicativo (antes do carregamento da interface do usuário), para defini-lo como configurações globais padrão:

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

}

Dessa forma, você mantém o código do seu UIViewController limpo e sempre pode substituí-lo, se desejar.

Lukasz
fonte
41

O iOS introduz a propriedade layoutMargins nas células E nas visualizações de tabela.

Esta propriedade não está disponível no iOS 7.0, portanto, verifique antes de atribuí-la!

No entanto, a Apple adicionou uma propriedade chamada preservesSuperviewLayoutMargins ao seu celular que impedirá que ele herde as configurações de margem do seu Table View. Dessa forma, suas células podem configurar suas próprias margens, independentemente da exibição da tabela. Pense nisso como uma substituição.

Essa propriedade é chamada preservesSuperviewLayoutMargins , e defini-la como NO pode permitir que você substitua as configurações layoutMargin da Table View pela configuração layoutMargin da sua própria célula. Isso economiza tempo ( você não precisa modificar as configurações da Visualização da tabela ) e é mais conciso. Consulte a resposta de Mike Abdullah para obter uma explicação detalhada.

NOTA: esta é a implementação apropriada e menos confusa, conforme expresso na resposta de Mike Abdullah; definir preserves da sua célulaSuperviewLayoutMargins = NO garantirá que a exibição da tabela não substitua as configurações da célula.

Primeiro passo - Configure as margens da sua célula:

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

Definir a propriedade preservesSuperviewLayoutMargins em sua célula como NO deve impedir que a exibição da tabela substitua as margens da célula. Em alguns casos, parece não funcionar corretamente.

Segunda etapa - Somente se tudo falhar, você poderá forçar com força suas margens do Table View:

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

... e lá vai você! Isso deve funcionar no iOS 8 e no iOS 7.

Nota: testado usando o iOS 8.1 e 7.1, no meu caso, eu só precisava usar o primeiro passo desta explicação.

A segunda etapa é necessária apenas se você tiver uma célula despovoada abaixo das células renderizadas, ou seja. se a tabela for maior que o número de linhas no modelo de tabela. Não seguir o segundo passo resultaria em diferentes deslocamentos do separador.

O rei da bruxaria
fonte
1
Você não precisa procurar seletores no willDisplayCellmétodo, pois o próprio método já é iOS 8+ e nunca será chamado a partir de versões mais antigas.
Rivera
38

No Swift, é um pouco mais irritante porque layoutMarginsé uma propriedade, então você deve substituir o getter e o setter.

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

Isso fará efetivamente layoutMarginssomente leitura, o que, no meu caso, está bem.

Swilliams
fonte
Somente essa solução funcionou para mim. E não precisei adicionar código de linhas adicional nos métodos. Eu usei células personalizadas.
Ramis
2
Para célula estática, exceto no layoutMargins, você ainda precisa alterar o estilo do separador da célula para "Custom Insets" e definir o valor esquerdo como "0" no storyboard.
precisa saber é o seguinte
22

Para o iOS 9, você precisa adicionar:

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

Para mais detalhes, consulte a pergunta .

Julian Król
fonte
12
é engraçado adicionar algum código para cada versão, para que a aparência inicial permaneça a mesma ... #
Christian
20

Extensão Swift 2.0

Eu só queria compartilhar uma extensão que fiz para remover as margens dos separadores de células do tableview.

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

Usado no contexto:

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

    cell.removeMargins()
    return cell
Dan Beaulieu
fonte
15

Rápido:

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
}
Alexander Volkov
fonte
11

Eu fiz o trabalho fazendo o seguinte:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
ideawu
fonte
9

Quanto ao que o cdstamper sugeriu em vez da exibição da tabela, adicionar linhas abaixo no método layoutSubview da célula funciona para mim.

- (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];
        }
}
Vijay VS
fonte
9

Exemplo do 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
    }
}
mkz
fonte
9

Depois de muita investigação ...

Aqui está a única maneira de controlar totalmente essas coisas (que eu poderia encontrar)

Controlar totalmente as inserções do separador e as margens do layout em cada célula. Faça isso no willDisplayCellmétodo em seu 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)
}

O objeto de célula controla o separador e contentViewcontrola todo o resto. Se os espaços inseridos do separador estiverem aparecendo em uma cor inesperada, isso deve resolver:

cell.backgroundColor = cell.contentView.backgroundColor
Matjan
fonte
8

Solução simples no Swift para iOS 8 com uma personalizaçãoUITableViewCell

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

Dessa maneira, você está definindo layoutMargine separatorInsetapenas uma vez, em vez de fazê-lo para cada um, willDisplayCellcomo sugere a maioria das respostas acima.

Se você estiver usando um costume, UITableViewCelleste é o local correto para fazê-lo. Caso contrário, você deve fazê-lo tableView:cellForRowAtIndexPath.

Apenas mais uma dica: você não precisa definir preservesSuperviewLayoutMargins = falseporque o valor padrão já está NO!

Francesco Vadicamo
fonte
8

Para mim, a linha simples fez o trabalho

cell.layoutMargins = UIEdgeInsetsZero
apinho
fonte
chamou isso no método delegado cellForRowAtIndexPath. Boa resposta :)
saintjab
7

Basta adicionar o código abaixo para resolver este programa.

Boa sorte para você!

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

}
JimmyChang
fonte
5

Lukasz responde em 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
    }
Naka
fonte
5

Este é o código que está funcionando para mim, no 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)
    }
}

Isso me parece mais limpo (por enquanto), já que todos os ajustes de borda / margem de cell / tableView são feitos no tableView:willDisplayCell:forRowAtIndexPath:método, sem sobrecarregar o código desnecessário tableView:cellForRowAtIndexPath:.

Btw, estou apenas configurando o separatorInset / layoutMargins à esquerda da célula, porque nesse caso não quero estragar minhas restrições que configurei na minha célula.

Código atualizado para 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)
        }
    }
Ivan
fonte
O que exatamente não está funcionando para você? Acabei de testar esse código no simulador do iPhone 5, com o iOS 8.1 SDK instalado, e tudo está como estava quando eu originalmente publiquei esta resposta. O código foi compilado e executado com o Xcode 6.1.1.
Ivan
4

A maioria das respostas estão mostrando inserções de separação e as margens de layout a ser definido através de uma variedade de métodos (ou seja, viewDidLayoutSubviews, willDisplayCell, etc) para as células e tableviews, mas eu descobri que apenas colocá-los em cellForRowAtIndexPathobras grandes. Parece o caminho mais limpo.

// 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];
inorganik
fonte
4

Use o trecho de código abaixo para evitar problemas indesejados de preenchimento para o UITableView no IOS 8 e 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];
    }
}
Anooj VM
fonte
4

Em vez de atualizar preservesSuperviewLayoutMarginse layoutMarginssempre que a célula rolar (usando willDisplayCell), sugiro fazer isso uma vez em 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

}
Rudolf Adamkovič
fonte
4

Aqui está uma maneira fácil de remover globalmente a inserção.

Em UITableViewCell+Extensions.swift:

import UIKit

extension UITableViewCell {

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

}

Em AppDelegate application:didFinishLaunchingWithOptions::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

Você pode pensar em a) também substituir separatorInseta extensão ou b) definir o proxy de aparência para layoutMargins. Nem vai funcionar. Mesmo que separatorInsetseja indicado como uma propriedade, tentar substituí-lo como uma propriedade (ou método) gera erros de compilador. E definindo o proxy aparência de UITableViewCell's layoutMargins(ou, para essa matéria, também definindo os proxies aparência de UITableView' s layoutMarginse separatorInset) não tem efeito.

Scott Gardner
fonte
3

No iOS8:

Adicionando isso à minha subclasse UITableViewCell:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

e isso para "tableView: cellForRowAtIndexPath" ou "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

Trabalhou para mim.

Saru
fonte
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;
}

Para qualquer célula específica que você deseja ocultar o separador.

xmurobi
fonte
2

Depois de ter visto as respostas no terceiro andar, tentei descobrir qual era a relação de configurar o separador entre o TableView e o TableViewCell e fiz alguns testes. Aqui estão as minhas conclusões:

  1. podemos considerar que definir o separador da célula como zero deve mover o separador em duas etapas: o primeiro passo é definir o separador da célula como zero. O segundo passo é definir o marginlayout da célula como zero.

  2. defina o conjunto separador do TableView e o marginlayout pode afetar o conjunto separador da célula . No entanto, a partir do teste, acho que o conjunto separador do TableView parece inútil, o marginlayout do TableView pode realmente afetar o marginginout da célula .

  3. set PreservesSuperviewLayoutMargins = false da célula pode cortar o efeito de margem do TableView nas células.

  4. uma das soluções:

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

Esta é a minha solução. Isso se aplica à subclasse de célula customizada, basta adicioná-los à subclasse.

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

2)

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

E é conveniente que você possa personalizar a posição do separador sem solicitar ao designer que desenhe um para você ..........

Guoyu
fonte
1

De uma forma mais compacta do que a resposta mais votada ...

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

}

subharb
fonte
1

Adicionando este trecho, simples e elegante no Swift funciona para mim no iOS8 :)

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

Isso funcionou perfeitamente para mim no iOS 8 e iOS 9.

Para 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;
    }
jithin
fonte