Home > Enterprise >  Swift: UITableView Separator lines break layout constraints
Swift: UITableView Separator lines break layout constraints

Time:04-21

So I have the following code that creates a TableView:

    contentView.addSubview(carsTableView)
    carsTableView.translatesAutoresizingMaskIntoConstraints = false
    carsTableView.backgroundColor = r.darkGray
    carsTableView.dataSource = self
    carsTableView.isScrollEnabled = false
    carsTableView.allowsSelection = true
    carsTableView.delegate = self
    
    carsTableView.separatorStyle = UITableViewCell.SeparatorStyle.singleLine
    carsTableView.separatorColor = r.lightGray
    carsTableView.separatorInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    
    carsTableView.register(CarCell.self, forCellReuseIdentifier: "CarCell")

Note that I use a single line separator. The following code are constraints for my Cell "CarCell"

NSLayoutConstraint.activate([
        carView.heightAnchor.constraint(equalToConstant: 120),
        carView.topAnchor.constraint(equalTo: contentView.topAnchor),
        carView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
        carView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
        carView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
        
        carImageView.leadingAnchor.constraint(equalTo: carView.leadingAnchor, constant: 15),
        carImageView.centerYAnchor.constraint(equalTo: carView.centerYAnchor),
        carImageView.heightAnchor.constraint(equalToConstant: carImageWidthAndHeight),
        carImageView.widthAnchor.constraint(equalToConstant: carImageWidthAndHeight),
        
        carImage.widthAnchor.constraint(equalTo: carImageView.widthAnchor),
        carImage.heightAnchor.constraint(equalTo: carImageView.heightAnchor),
        carImage.centerYAnchor.constraint(equalTo: carImageView.centerYAnchor),
        carImage.centerXAnchor.constraint(equalTo: carImageView.centerXAnchor),
        
        stringStack.leadingAnchor.constraint(equalTo: carImageView.trailingAnchor, constant: 20),
        stringStack.centerYAnchor.constraint(equalTo: carView.centerYAnchor),
        
        editButton.trailingAnchor.constraint(equalTo: carView.trailingAnchor, constant: -15),
        editButton.centerYAnchor.constraint(equalTo: carView.centerYAnchor),
        
    ])

The result is a perfectly fine TableView which looks exactly like it should. However, the separator line breaks the height constraint from 120 to 120.33. How can I avoid that? I am honestly amazed by the fact that no one seems to have a similar problem. How do I get around it? The difference is obviously not noticeable, but the constraint issues bother me in the console. I'd like to have it run without throwing errors...

CodePudding user response:

This is a common issue related to the way UIKit lays out table views and cells.

You're seeing 120 to 120.3333, but if you run the app on a device with @2x screen scale, the message will be 120.5.

When calculating "single pixel" lines, @2x devices can only use whole or 1/2 points, and @3x devices can only use whole, 1/3 or 2/3 points.

It is safe to ignore, but if you want to get rid of the error / warning messages, give your cells subview(s) a bottom constraint with less-than-required priority.

For example (I'm assuming from the code you posted that carImageView, carImage, stringStack, editButton are all subviews of carView):

    let c  = carView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
    c.priority = .required - 1
    
    NSLayoutConstraint.activate([
        
        // don't use this one
        //carView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
        
        // activate the less-than-required bottom constraint
        c,
        
        // the rest of your constraints....
        carView.heightAnchor.constraint(equalToConstant: 120),
        carView.topAnchor.constraint(equalTo: contentView.topAnchor),
        carView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
        carView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),

        // and so on....
  • Related