El separador 0 UITableView de iOS 8 no funciona

Resuelto user3570727 asked hace 54 años • 43 respuestas

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

¿ Cómo elimino los UITableViewCellmárgenes del separador?

user3570727 avatar Jan 01 '70 08:01 user3570727
Aceptado

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

Esta propiedad no está disponible en iOS 7.0, por lo que debes asegurarte de verificarla antes de asignarla.

La solución fácil es crear una subclasificación de su celda y anular la propiedad de 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 de forma condicional, siga leyendo.


Además de la layoutMarginspropiedad, Apple ha agregado una propiedad a su celda que evitará que herede la configuración de márgenes de su 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.

Esta propiedad se llama preservesSuperviewLayoutMarginsy establecerla en NOpermitirá que la layoutMarginconfiguración de la celda anule lo que layoutMarginesté configurado en su TableView. Ahorra tiempo ( no es necesario modificar la configuración de la Vista de tabla ) y es más conciso. 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. Configurar las celdas preservesSuperviewLayoutMargins=NOgarantizará que la vista de tabla no anule la configuración de la celda. Si realmente desea que toda la vista de la 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];
    }
}

Rápido 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 la vista de su tabla anule los márgenes de su celda. En algunos casos, parece que no funciona correctamente.

Si todo falla, puede forzar bruscamente los márgenes de la 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];
    }
} 

Rápido 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 cellLayoutMarginsFollowReadableWidthsi NOdesea personalizar los recuadros o los márgenes. Su kilometraje puede variar, esto no está muy bien documentado.

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

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

Rápido 4:

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

(El código anterior del separador UITableView de iOS 8 insertado 0 no funciona )

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

Inspector de atributos de vista de tabla TableViewCellSizeInspector

NOTA: iOS 11 cambia y simplifica gran parte de este comportamiento; próximamente habrá una actualización...

emma ray avatar Sep 16 '2014 20:09 emma ray

Arg!!! Después de jugar, haga esto en su Cellsubclase:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

o configurarlo cell.layoutMargins = UIEdgeInsetsZero;para arreglarlo por mí.

user3570727 avatar Sep 10 '2014 18:09 user3570727

Tomémonos un momento para comprender el problema antes de lanzarnos a la carga a ciegas para intentar solucionarlo.

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

iOS 8 introduce 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 anteriores.

Lo mejor que podemos decir es que, al diseñar su línea separadora, UITableViewCellelige respetar el margen de diseño izquierdo y lo utiliza para restringir el recuadro izquierdo.

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

  • Establezca el margen de diseño izquierdo en0
  • Detener cualquier margen heredado que anule eso

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

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

Cosas a tener en cuenta:

  • Este código solo necesita ejecutarse una vez por celda (después de todo, solo estás configurando las propiedades de la celda), y no hay nada especial en cuándo eliges ejecutarlo. Haz lo que te parezca más limpio.
  • Lamentablemente, ninguna propiedad está disponible para configurar en Interface Builder, pero puede especificar un atributo de tiempo de ejecución definido por el usuario si preservesSuperviewLayoutMarginslo desea.
  • Claramente, si su aplicación también apunta 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 las vistas ancestrales (como la tabla) para que 0también tengan margen izquierdo, pero esto parece intrínsecamente más propenso a errores ya que no controla toda la jerarquía.
  • Probablemente sería un poco más limpio establecer solo el margen izquierdo 0y dejar los demás así.
  • Si desea insertar un 0 en los separadores "adicionales" que UITableViewse dibujan en la parte inferior de las tablas de estilo simple, supongo que será necesario especificar la misma configuración a nivel de tabla también (¡no he probado este!)
Mike Abdullah avatar Nov 09 '2014 10:11 Mike Abdullah

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 fallará en iOS 7.x. Entonces, la mejor manera sería verificar si layoutMarginsexiste primero antes setLayoutMargins:UIEdgeInsetsZero.

Ricky avatar Sep 11 '2014 12:09 Ricky