iOS 8 UITableView separador inserto 0 no funciona

662

Tengo una aplicación en la que UITableViewel recuadro separador está configurado con valores personalizados: derecha 0, izquierda 0. Esto funciona perfectamente iOS 7.x, sin embargo iOS 8.0, veo que la inserción del separador está configurada en el valor predeterminado de 15a la derecha. Aunque en los archivos xib que configuró 0, todavía se muestra incorrectamente.

¿Cómo UITableViewCellelimino los márgenes del separador?

usuario3570727
fuente
¿Has intentado configurar el recuadro en 0.001 en lugar de 0? Recuerdo haber tenido un problema similar en el que el recuadro de borde no reaccionaba a 0 pero sí reaccionaba a 0.001 (o algo similar pequeño).
Freshking
Lo intenté y tampoco funcionó ..
user3570727
44
Entonces sugeriría configurar el color de los separadores [UIColor clearColor]y dibujar sus propios separadores. Eres mucho más flexible de esa manera.
Freshking
1
Todavía no puedo creer que este no sea uno de los UITableViewCellSeparatorStylevalores predeterminados. Incluso la respuesta aceptada es un truco realmente sucio en mi opinión.
Enrico Susatyo

Respuestas:

1071

iOS 8.0 presenta la propiedad layoutMargins en celdas Y vistas de tabla.

Esta propiedad no está disponible en iOS 7.0, por lo que debe asegurarse de verificar antes de asignarla.

La solución fácil es subclasificar su celda y anular la propiedad de los márgenes de diseño como lo sugiere @ user3570727. Sin embargo, perderá cualquier comportamiento del sistema, como heredar márgenes del Área segura, por lo que no recomiendo la siguiente solución:

(C objetivo)

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

(rápido 4.2):

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

Si no desea anular la propiedad, o necesita establecerla condicionalmente, siga leyendo.


Además de la layoutMarginspropiedad, Apple ha agregado una propiedad a su celda que evitará que herede la configuración de margen de la Vista de tabla. Cuando se establece esta propiedad, sus celdas pueden configurar sus propios márgenes independientemente de la vista de tabla. Piense en ello como una anulación.

Se llama a esta propiedad preservesSuperviewLayoutMarginsy establecerla en NOpermitirá que la layoutMarginconfiguración de la celda anule lo que layoutMarginesté configurado en su TableView. Ambos ahorran tiempo ( no tiene que modificar la configuración de la Vista de tabla ) y son más concisos. Consulte la respuesta de Mike Abdullah para obtener una explicación detallada.

NOTA: lo que sigue es una implementación limpia para una configuración de margen a nivel de celda , como se expresa en la respuesta de Mike Abdullah. La configuración de su celda preservesSuperviewLayoutMargins=NOasegurará que su Vista de tabla no anule la configuración de la celda. Si realmente desea que toda su vista de tabla tenga márgenes consistentes, ajuste su código en consecuencia.

Configure los márgenes de su celda:

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

Establecer la preservesSuperviewLayoutMarginspropiedad en su celda en NO debería evitar que su vista de tabla anule los márgenes de su celda. En algunos casos, parece no funcionar correctamente.

Si todo falla, puede aplicar fuerza bruta a los márgenes de Vista de tabla:

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

... y ahí lo tienes! Esto debería funcionar en iOS 7 y 8.


EDITAR: Mohamed Saleh me llamó la atención sobre un posible cambio en iOS 9. Es posible que deba configurar la Vista de tabla cellLayoutMarginsFollowReadableWidthenNO si desea personalizar inserciones o márgenes. Su kilometraje puede variar, esto no está muy bien documentado.

Esta propiedad solo existe en iOS 9, así que asegúrese de verificar antes de configurar.

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

Swift 4:

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

(el código anterior del separador 0 UITableView del separador UITableView 0 no funciona )

EDITAR: Aquí hay un enfoque puro de Interface Builder:

TableViewAttributesInspector TableViewCellSizeInspector

NOTA: iOS 11 cambia y simplifica gran parte de este comportamiento, se lanzará una actualización ...

cdstamper
fuente
2
Para las vistas de tabla dentro de un UIPopoverController, tuve que hacer ambas cosas como se muestra arriba, en lugar de solo en willDisplayCell.
Zhang
44
También descubrí que, a pesar de todo el código anterior, todavía tenía que agregar cell.preservesSuperviewLayoutMargins = NOpor sugerencia de @ bffmike o después de desplazarme por las formas en que aparecerían las inserciones. (wtf ??)
inorganik
¿Qué sucede si queremos establecer el margen solo para un tipo de celda en una vista de tabla agrupada?
SAHM
Puede intentar configurarlo en willDisplayCell y ver si eso realmente funciona (tiene un controlador en la celda, por lo que debería ser trivial). Si no es así, debemos presentar un error. Los márgenes de diseño específicos de la celda deberían ser posibles, OMI.
cdstamper
2
Esto funcionó para mí con la adición de cell.preservesSuperviewLayoutMarginsmi método de fuente de datos:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
mts
257

Arg !!! Después de jugar haciendo esto en tu Cellsubclase:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

o configurando el cell.layoutMargins = UIEdgeInsetsZero;arreglado para mí.

usuario3570727
fuente
13
La primera solución en esta respuesta funcionó para mí, la segunda no funcionó.
spybart
55
No solo use cell.layoutMargins = UIEdgeInsetsZero; ya que se bloqueará en iOS 7.x. Es mejor verificar si el selector existe primero antes de usarlo. Vea mi solución a continuación.
Ricky
3
No está configurando cell.layoutMargins ... Esta solución funciona muy bien cuando ya tienes celdas personalizadas.
Sjoerd realiza
11
¡Esto funcionará bien en iOS 7, ya que no se llamará al método! Sin embargo, también debe establecer los márgenes de diseño de la vista de tabla, o no funcionará.
cdstamper
2
anular el acceso funcionó para mí. pero todas las otras soluciones no lo hicieron. incluso configurar el separatorInseten IB no funcionó. También hay un problema con los colores de fondo de la vista de tabla. Esto es realmente algo enfermo.
glasz
178

Dediquemos un momento a comprender el problema antes de cargar a ciegas para intentar solucionarlo.

Un rápido vistazo al depurador le dirá que las líneas de separación son subvistas de UITableViewCell. Parece que la propia célula asume una gran cantidad de responsabilidad por el diseño de estas líneas.

iOS 8 presenta el concepto de márgenes de diseño . De forma predeterminada, los márgenes de diseño de una vista están 8pten todos los lados y se heredan de las vistas de antepasados.

Lo mejor que podemos decir es que, al diseñar su línea de separación, UITableViewCellelige respetar el margen de diseño de la izquierda, utilizándolo para restringir el recuadro izquierdo.

Uniendo todo eso, para lograr la inserción deseada de cero, necesitamos:

  • Establezca el margen de diseño izquierdo en 0
  • Detenga cualquier margen heredado que anule ese

Dicho así, es una tarea bastante simple de lograr:

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

Cosas a tener en cuenta:

  • Este código solo debe ejecutarse una vez por celda (después de todo, solo está configurando las propiedades de la celda), y no tiene nada de especial cuando elige ejecutarlo. Haz lo que te parezca más limpio.
  • Lamentablemente, ninguna de las propiedades está disponible para configurar en Interface Builder, pero puede especificar un atributo de tiempo de ejecución definido por el usuario preservesSuperviewLayoutMarginssi lo desea.
  • Claramente, si su aplicación también se dirige a versiones anteriores del sistema operativo, deberá evitar ejecutar el código anterior hasta que se ejecute en iOS 8 y superior.
  • En lugar de configurar preservesSuperviewLayoutMargins, puede configurar vistas de antepasados ​​(como la tabla) para que también tengan 0margen izquierdo, pero esto parece inherentemente más propenso a errores ya que no controla toda esa jerarquía.
  • Probablemente sería un poco más limpio establecer solo el margen izquierdo 0y dejar a los demás.
  • Si desea tener un recuadro 0 en los separadores "extra" que se UITableViewdibujan en la parte inferior de las tablas de estilo plano, supongo que también requerirá especificar la misma configuración a nivel de tabla (¡no lo he probado!)
Mike Abdullah
fuente
3
¡Gracias! Esta es realmente la respuesta más concisa. Mucho mejor que anular dos métodos y forzarlo de forma bruta.
LunaCodeGirl
16
En iOS 8, para mí, esto no funcionaría sin[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
davetw12
1
Tienes mi voto, gracias por la explicación clara. Solo mencionaré que TableView en sí también tiene un diseño de márgenes que puede necesitar establecerse además del separatorInset, en algunos casos.
cdstamper
@ davetw12 y @cdstamper ¿Puede proporcionar alguna evidencia de esto? Todas mis exploraciones hasta ahora dicen que configurar todo layoutMarginsy preservesSuperviewLayoutMarginsen la celda es todo lo que se requiere. Cualquier otra cosa se siente como confiar en el vudú.
Mike Abdullah
3
No, no es una forma de vudú @MikeAbdullah. Para evitar el valor predeterminado separatorInsetde a UITableViewCellen iOS 8, debe establecer el conjunto UIEdgeInsetsen cero tanto en el UITableViewcomo en el UITableViewCell. Si no hace las dos cosas, todavía tendrá un recuadro izquierdo mayor que cero. Lo he confirmado varias veces.
davetw12
58

Creo que esta es la misma pregunta que hice aquí: Eliminar SeparatorInset en iOS 8 UITableView para XCode 6 iPhone Simulator

En iOS 8 , hay una nueva propiedad para todos los objetos que heredan UIView. Por lo tanto, la solución para configurar SeparatorInseten iOS 7.x no podrá eliminar el espacio en blanco que ve en UITableView en iOS 8.

La nueva propiedad se llama " 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

La solución:-

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

Si configura cell.layoutMargins = UIEdgeInsetsZero;sin verificar si layoutMarginsexiste, la aplicación se bloqueará en iOS 7.x. Entonces, la mejor manera sería verificar si layoutMarginsexiste antes setLayoutMargins:UIEdgeInsetsZero.

Ricky
fuente
¿Cómo se puede usar este enfoque si el objetivo de implementación se establece en iOS 7?
Petar
Puse el código para tableView en viewDidLoad y estoy trabajando bien. Creo que no es necesario llamarlos cada vez en willDisplayCell ().
Abdullah Umer
46

Puede usar UIAppearance una vez, al iniciar la aplicación (antes de cargar la IU), para establecerla como configuración global predeterminada:

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

}

De esta manera, mantienes limpio el código de tu controlador UIView y siempre puedes anularlo si lo deseas.

Lukasz
fuente
41

iOS presenta la propiedad layoutMargins en celdas Y vistas de tabla.

Esta propiedad no está disponible en iOS 7.0, por lo que debe asegurarse de verificar antes de asignarla.

Sin embargo, Apple ha agregado una propiedad llamada preservasSuperviewLayoutMargins a su celda que evitará que herede la configuración de margen de su Vista de tabla. De esta manera, sus celdas pueden configurar sus propios márgenes independientemente de la vista de tabla. Piense en ello como una anulación.

Esta propiedad se llama preservesSuperviewLayoutMargins , y establecerla en NO puede permitirle anular la configuración de diseño de la vista de tabla con la configuración de diseño de su propia celda. Ambos ahorran tiempo ( no tiene que modificar la configuración de la Vista de tabla ) y son más concisos. Consulte la respuesta de Mike Abdullah para obtener una explicación detallada.

NOTA: esta es la implementación adecuada y menos complicada, como se expresa en la respuesta de Mike Abdullah; establecer las reservas de su celdaSuperviewLayoutMargins = NO asegurará que su Vista de tabla no anule la configuración de la celda.

Primer paso: configure los márgenes de su celda:

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

Establecer la propiedad preservasSuperviewLayoutMargins en su celda en NO debería evitar que su vista de tabla anule los márgenes de su celda. En algunos casos, parece no funcionar correctamente.

Segundo paso: solo si todo falla, puede aplicar fuerza bruta a los márgenes de la Vista de tabla:

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

... y ahí lo tienes! Esto debería funcionar tanto en iOS 8 como en iOS 7.

Nota: probado con iOS 8.1 y 7.1, en mi caso solo necesitaba usar el primer paso de esta explicación.

El segundo paso solo es necesario si tiene una celda despoblada debajo de las celdas renderizadas, es decir. si la tabla es mayor que el número de filas en el modelo de tabla. No hacer el segundo paso daría como resultado diferentes compensaciones de separador.

Rey Mago
fuente
1
No necesita buscar selectores en el willDisplayCellmétodo ya que el método en sí ya es iOS 8+ y nunca se llamará desde versiones anteriores.
Rivera
38

En Swift es un poco más molesto porque layoutMarginses una propiedad, por lo que debes anular el captador y el definidor.

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

Esto efectivamente hará layoutMarginssolo lectura, que en mi caso está bien.

swilliams
fuente
Solo esta solución funcionó para mí. Y no necesitaba agregar código de líneas adicional en los métodos. Usé celdas personalizadas.
Ramis
2
Para las celdas estáticas, excepto para anular el diseño de los márgenes, aún debe cambiar el estilo del separador de la celda a "Inserciones personalizadas" y establecer el valor izquierdo a "0" en el guión gráfico.
hufeng03
22

Para iOS 9 necesitas agregar:

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

Para más detalles, consulte la pregunta .

Julian Król
fuente
12
es divertido agregar un código para cada versión para que la apariencia inicial permanezca igual ...
Christian
20

Extensión Swift 2.0

Solo quería compartir una extensión que hice para eliminar los márgenes de los separadores de celdas de la vista de tabla.

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 en contexto:

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

    cell.removeMargins()
    return cell
Dan Beaulieu
fuente
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
fuente
11

Lo hice funcionar haciendo esto:

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

En cuanto a lo que sugirió cdstamper en lugar de la vista de tabla, agregar líneas a continuación en el método layoutSubview de la celda funciona para mí.

- (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
fuente
9

Ejemplo de 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
fuente
9

Después de mucha investigación ...

Aquí está la única forma de controlar completamente estas cosas (que pude encontrar)

Para controlar por completo tanto las separaciones como los márgenes de diseño en cada celda. Haga esto en el willDisplayCellmétodo en su 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)
}

El objeto de celda controla el separador, y contentViewcontrola todo lo demás. Si los espacios de inserción de su separador se muestran en un color inesperado, esto debería resolverlo:

cell.backgroundColor = cell.contentView.backgroundColor
Matjan
fuente
8

Solución simple en Swift para iOS 8 con una costumbreUITableViewCell

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

De esta manera, está configurando layoutMarginy separatorInsetsolo una vez en lugar de hacerlo para cada uno, willDisplayCellcomo sugiere la mayoría de las respuestas anteriores.

Si está utilizando una costumbre, UITableViewCelleste es el lugar correcto para hacerlo. De lo contrario, deberías hacerlo tableView:cellForRowAtIndexPath.

Solo otra pista: ¡no necesita configurarlo preservesSuperviewLayoutMargins = falseporque el valor predeterminado ya está NO!

Francesco Vadicamo
fuente
8

Para mí, la línea simple hizo el trabajo

cell.layoutMargins = UIEdgeInsetsZero
apinho
fuente
llamado esto en el método de delegado cellForRowAtIndexPath. Buena respuesta :)
saintjab
7

Simplemente agregue el código a continuación puede resolver este programa.

¡Buena suerte para ti!

-(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
fuente
5

Lukasz responde en 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
fuente
5

Este es el código que funciona para mí, en 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)
    }
}

Esto me parece el más limpio (por ahora), ya que todos los ajustes de borde / margen de cell / tableView se realizan en el tableView:willDisplayCell:forRowAtIndexPath:método, sin meter código innecesario tableView:cellForRowAtIndexPath:.

Por cierto, solo estoy configurando el separador izquierdo de la celdaInset / layoutMargins, porque en este caso no quiero arruinar las restricciones que he configurado en mi celda.

Código actualizado a 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
fuente
¿Qué no te funciona exactamente? Acabo de probar este código en el simulador de iPhone 5, con el SDK de iOS 8.1 instalado, y todo está como estaba cuando publiqué originalmente esta respuesta. El código fue compilado y ejecutado con Xcode 6.1.1.
Ivan
4

La mayoría de las respuestas están mostrando inserciones de separación y márgenes de la disposición que se establecen a través de una variedad de métodos (es decir, viewDidLayoutSubviews, willDisplayCell, etc) para las células y tableviews, pero he encontrado que simplemente poniendo estos en cellForRowAtIndexPathobras grandes. Parece la forma más limpia.

// 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
fuente
4

Utilice el fragmento de código a continuación para evitar problemas de relleno no deseados para UITableView en iOS 8 y 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
fuente
4

En lugar de actualizar preservesSuperviewLayoutMarginsy layoutMarginscada vez que la celda se desplaza (usando willDisplayCell), sugeriría hacerlo una vez en 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č
fuente
4

Aquí hay una manera fácil de eliminar globalmente el recuadro.

En UITableViewCell+Extensions.swift:

import UIKit

extension UITableViewCell {

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

}

En AppDelegate application:didFinishLaunchingWithOptions::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

Puede pensar en a) también simplemente anular separatorInseten la extensión, o b) establecer el proxy de apariencia para layoutMargins, en su lugar. Ninguno de los dos funcionará. Aunque separatorInsetse indica que es una propiedad, intentar anularla como una propiedad (o método) genera errores de compilación. Y establecer el proxy apariencia de UITableViewCell's layoutMargins(o, para el caso, también el establecimiento de los proxies apariencia de UITableView' s layoutMarginsy separatorInset) no tiene ningún efecto.

Scott Gardner
fuente
3

En iOS8:

Agregando esto a mi subclase UITableViewCell:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

y esto a "tableView: cellForRowAtIndexPath" o "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

Trabajó para mi.

Saru
fuente
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 cualquier celda específica que desee ocultar el separador.

xmurobi
fuente
2

Después de haber visto las respuestas en el piso 3, traté de averiguar cuál es la relación de configurar el separador entre TableView y TableViewCell e hice algunas pruebas. Aquí están mis conclusiones:

  1. podemos considerar que establecer el separador de la celda en cero debe mover el separador en dos pasos: el primer paso es establecer el separador de la celda en cero. El segundo paso es establecer el margen de la celda en cero.

  2. establecer el TableView de separatorinset y marginlayout puede afectar de la Célula separatorinset . Sin embargo, a partir de la prueba, encuentro que el separador de inserción de TableView parece ser inútil, la distribución de margen de TableView realmente puede afectar la distribución de margen de la celda .

  3. establecer Cell's PreservesSuperviewLayoutMargins = false, puede cortar el efecto de margen de TableView en las celdas.

  4. Una de las soluciones:

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

Esta es mi solución Esto se aplica a la subclase de celda personalizada, solo agréguelas a la subclase.

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

2)

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

Y es conveniente que pueda personalizar la posición del separador sin pedirle a su diseñador que dibuje uno para usted ..........

Guoyu
fuente
1

De una forma más compacta que la respuesta más 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
fuente
1

Agregar este fragmento, simple y elegante en Swift me funciona en iOS8 :)

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

Esto funcionó perfectamente para mí en 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
fuente