objective-c - Separatore di iOS 8 UITableView 0 non funzionante





swift ios8 (26)


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

Per ogni cella specifica, vuoi nascondere il separatore.

Ho un'app in cui il separatore di UITableView è impostato su valori personalizzati - Destra 0 , Sinistra 0 . Funziona perfettamente su iOS 7.x , tuttavia in iOS 8.0 vedo che il separatore è impostato sul valore predefinito di 15 sulla destra. Anche se nei file xib è impostato su 0 , viene comunque visualizzato in modo errato.

Come rimuovere i margini del separatore di UITableViewCell ?




Dopo molte indagini ...

Ecco l'unico modo per controllare completamente questa roba (che potrei trovare)

Per controllare completamente entrambi i separatori e i margini di layout su ogni cella. Fai questo nel metodo willDisplayCell sul tuo 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)
}

L'oggetto cella controlla il separatore e contentView controlla tutto il resto. Se i tuoi riquadri separatori sono mostrati in un colore inaspettato, questo dovrebbe risolverlo:

cell.backgroundColor = cell.contentView.backgroundColor



Estensione Swift 2.0

Volevo solo condividere un'estensione che ho fatto per rimuovere i margini dai separatori di celle 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
        }
    }
}

Utilizzato nel contesto:

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

    cell.removeMargins()
    return cell



Utilizzare lo snippet di codice seguente per evitare problemi di padding indesiderati per UITableView in 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];
    }
}



Basta aggiungere sotto il codice in grado di risolvere questo programma.

Buona fortuna a te!

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

}



Lukasz risponde in 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
    }



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



Prendiamoci un momento per capire il problema prima di caricarci alla cieca per tentare di risolverlo.

Un rapido colpo nel debugger ti dirà che le linee di separazione sono sottoview di UITableViewCell . Sembra che la cella stessa abbia una buona dose di responsabilità per il layout di queste linee.

iOS 8 introduce il concetto di margini di layout . Per impostazione predefinita, i margini di layout di una vista sono 8pt su tutti i lati e sono ereditati dalle viste degli antenati.

Come meglio possiamo dire, quando si stende la sua linea di separazione, UITableViewCell sceglie di rispettare il margine del layout di sinistra, usandolo per vincolare l'inserto sinistro.

Mettendo tutto ciò insieme, per ottenere l'insetto desiderato di veramente zero, abbiamo bisogno di:

  • Imposta il margine sinistro del layout su 0
  • Interrompere eventuali margini ereditati ignorando quello

Detto così, è un compito piuttosto semplice da raggiungere:

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

Cose da notare:

  • Questo codice deve essere eseguito solo una volta per cella (state solo configurando le proprietà della cella dopo tutto) e non c'è nulla di speciale quando si sceglie di eseguirlo. Fai quello che ti sembra più pulito.
  • Purtroppo nessuna delle due proprietà è disponibile per la configurazione in Interface Builder, ma se lo si desidera è possibile specificare un attributo di runtime definito dall'utente per preservesSuperviewLayoutMargins .
  • Chiaramente, se la tua app si rivolge anche a versioni precedenti del sistema operativo, dovrai evitare di eseguire il codice sopra fino all'esecuzione su iOS 8 e versioni successive.
  • Anziché impostare preservesSuperviewLayoutMargins , è possibile configurare le viste degli antenati (come la tabella) per avere anche 0 margine sinistro, ma questo sembra intrinsecamente più soggetto a errori poiché non si controlla l'intera gerarchia.
  • Probabilmente sarebbe leggermente più pulito per impostare solo il margine sinistro su 0 e lasciare che siano gli altri.
  • Se vuoi inserire un valore 0 sui separatori "extra" che UITableView disegna nella parte inferiore delle tabelle in stile semplice, suppongo che sarà necessario specificare le stesse impostazioni anche a livello di tabella (non ho provato questo!)



L'ho fatto funzionare in questo modo:

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



Questa è la mia soluzione. Questo vale per la sottoclasse di celle personalizzate, basta aggiungerle entrambe alla sottoclasse.

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

2.

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

Ed è conveniente che tu possa personalizzare la posizione del separatore senza chiedere al tuo disegnatore di disegnarne uno per te ..........




Per quanto riguarda il suggerimento di cdstamper al posto della vista tabella, l'aggiunta delle righe sottostanti nel metodo layoutSubview della cella funziona per me.

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



Questo è il codice che funziona per me, in 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)
    }
}

Questo mi sembra il più pulito (per ora), poiché tutte le correzioni bordo / margine di cella / tabellaView vengono eseguite nella tableView:willDisplayCell:forRowAtIndexPath: metodo, senza dover inserire codice non necessario in tableView:cellForRowAtIndexPath:

A proposito, sto solo impostando il separatore di sinistra della cellaInset / layoutMargins, perché in questo caso non voglio rovinare i miei vincoli che ho impostato nella mia cella.

Codice aggiornato 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)
        }
    }



Questo ha funzionato perfettamente per me su iOS 8 e iOS 9.

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



Invece di aggiornare preservesSuperviewLayoutMargins e layoutMargins ogni volta che la cella scorre (usando willDisplayCell ), ti suggerisco di farlo una volta in 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

}



Arg !!! Dopo averlo giocato, esegui questa operazione nella sottoclasse Cell :

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

o impostando il file cell.layoutMargins = UIEdgeInsetsZero; risolto per me.




Dopo aver visto le risposte al terzo piano, ho cercato di capire quale fosse il rapporto tra l'impostazione del separatore tra TableView e TableViewCell e fatto qualche test. Ecco le mie conclusioni:

  1. possiamo considerare che l'impostazione del separatore della cella a zero deve spostare il separatore in due passaggi: il primo passo è impostare il separatorinset della cella su zero. il secondo passo è quello di impostare il marginlayout della cella a zero.

  2. imposta il separatorinset di TableView e marginlayout può influenzare il separatorinset della cella. Tuttavia, dal test, ho trovato che il separatorinset del TableView sembra essere inutile, marginlayout di TableView può effettivamente influenzare marginlayout della cella.

  3. set Cell's PreservesSuperviewLayoutMargins = false, può tagliare l'effetto marginlayout di TableView su Cells.

  4. una delle soluzioni:

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



In un modo più compatto rispetto alla risposta più votata ...

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

}




È possibile utilizzare UIAppearance una volta, all'avvio dell'applicazione (prima che venga caricata l'interfaccia utente), per impostarlo come impostazioni globali predefinite:

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

}

In questo modo, manterrai pulito il codice di UIViewController e potrai sempre sostituirlo se lo desideri.




In iOS8:

Aggiungendo questo alla sottoclasse UITableViewCell:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

e questo a "tableView: cellForRowAtIndexPath" o "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

LAVORATO per me.




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
}



La maggior parte delle risposte mostra i separatori ei margini del layout impostati su una varietà di metodi (ad esempio, viewDidLayoutSubviews , willDisplayCell , ecc.) Per le celle e le visualizzazioni di tabelle, ma ho scoperto che il semplice inserimento di questi in cellForRowAtIndexPath funziona alla grande. Sembra il modo più pulito.

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



iOS 8.0 introduce la proprietà layoutMargins su celle E viste tabella.

Questa proprietà non è disponibile su iOS 7.0, quindi è necessario assicurarsi di controllare prima di assegnarlo!

Inoltre, Apple ha aggiunto una proprietà alla tua cella che gli impedirà di ereditare le impostazioni dei margini della tua Vista tabella. Quando questa proprietà è impostata, le tue celle possono configurare i propri margini indipendentemente dalla vista tabella. Pensalo come un override.

Questa proprietà si chiama preservesSuperviewLayoutMargins e impostandola su NO consentirà all'impostazione layoutMargin della cella di sovrascrivere qualsiasi layoutMargin sia impostato su TableView. Risparmia tempo ( non è necessario modificare le impostazioni della Vista tabella ) ed è più conciso. Si prega di fare riferimento alla risposta di Mike Abdullah per una spiegazione dettagliata.

NOTA: ciò che segue è un'implementazione pulita per un'impostazione del margine a livello di cella , come espressa nella risposta di Mike Abdullah. Impostazione delle conserve della cellaSuperviewLayoutMargins = NO garantisce che la vista tabella non sostituisca le impostazioni della cella. Se vuoi che l'intera vista tabella abbia margini coerenti, modifica il codice di conseguenza.

Imposta i margini della tua cella:

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

L'impostazione della proprietà preservesSuperviewLayoutMargins sulla tua cella su NO dovrebbe impedire alla vista tabella di ignorare i margini della cella. In alcuni casi, sembra non funzionare correttamente.

Se tutto fallisce, puoi forzare la forza bruta sui margini della vista tabella:

-(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 ci sei! Questo dovrebbe funzionare su iOS 7 e 8.

EDIT: Mohamed Saleh ha portato alla mia attenzione un possibile cambiamento in iOS 9. Potrebbe essere necessario impostare il valore di cellLayoutMarginsFollowReadableWidth di Table View su NO se si desidera personalizzare gli inserti oi margini. Il tuo chilometraggio può variare, questo non è documentato molto bene.

Questa proprietà esiste solo in iOS 9, quindi assicurati di controllare prima di impostare.

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

Swift 4:

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

(codice sopra da iOS 8 UITableView separator inset 0 non funziona )

EDIT: Ecco un approccio puro Interface Builder:

NOTA: iOS 11 cambia e semplifica gran parte di questo comportamento, un aggiornamento sarà imminente ...




Soluzione semplice in Swift per iOS 8 con UITableViewCell personalizzato

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

In questo modo stai impostando layoutMargin e separatorInset solo una volta invece di farlo per ogni willDisplayCell come willDisplayCell maggior parte delle risposte precedenti.

Se stai usando un UITableViewCell personalizzato, questo è il posto giusto per farlo. Altrimenti dovresti farlo in tableView:cellForRowAtIndexPath .

Un altro suggerimento: non è necessario impostare preservesSuperviewLayoutMargins = false perché il valore predefinito è già NO !




Per iOS 9 è necessario aggiungere:

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

Per maggiori dettagli si prega di fare riferimento alla question .




In Swift è leggermente più fastidioso perché layoutMargins è una proprietà, quindi devi scavalcare il getter e setter.

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

Questo renderà efficacemente layoutMargins sola lettura, che nel mio caso va bene.




Ho fatto questa domanda sulla loro pagina github e ho ricevuto una risposta da pomeriggio:

swift 2:

if let data = response.data {
    let json = String(data: data, encoding: NSUTF8StringEncoding)
    print("Failure Response: \(json)")
}

rapido 3:

if let data = response.data {
    let json = String(data: data, encoding: String.Encoding.utf8)
    print("Failure Response: \(json)")
}

https://github.com/Alamofire/Alamofire/issues/1059

Ho appena escluso la parte di codifica, in questo modo si è in grado di ottenere la risposta JSON anche in caso di errori.





ios objective-c swift uitableview ios8