4

I am trying to use auto sizing UITableView cells in swift with snapKit! relevant flags set on the UITableView are as follows:

self.rowHeight = UITableViewAutomaticDimension
self.estimatedRowHeight = 70.0

I have a UITextField defined in my customUITableviewCell class like:

var uidTextField: UITextField = UITextField()

and the initial setup of the text field in my custom UITableViewCell looks like this:

self.contentView.addSubview(uidTextField)
uidTextField.attributedPlaceholder = NSAttributedString(string: "Woo Hoo", attributes: [NSForegroundColorAttributeName:UIColor.lightGrayColor()])
uidTextField.textAlignment = NSTextAlignment.Left
uidTextField.font = UIFont.systemFontOfSize(19)
uidTextField.returnKeyType = UIReturnKeyType.Done
uidTextField.autocorrectionType = UITextAutocorrectionType.No
uidTextField.delegate = self
uidTextField.addTarget(self, action: "uidFieldChanged", forControlEvents: UIControlEvents.EditingChanged)
uidTextField.snp_makeConstraints { make in 
    make.left.equalTo(self.contentView).offset(10)
    make.right.equalTo(self.contentView)
    make.top.equalTo(self.contentView).offset(10)
    make.bottom.equalTo(self.contentView).offset(10)
}

when I run the code it shows up cut off and gives me an error in the console that reads:

Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead.

Is there something wrong with my autoLayout constraints or is this an issue with UIControls and autosizing of UITableView cells?

ChrisCorea
  • 152
  • 1
  • 8
CWineland
  • 615
  • 7
  • 18

1 Answers1

2

In SnapKit (and Masonry) you have to use negative values to add a padding to the right or bottom of a view. You are using offset(10) on your bottom constraint which causes the effect that the bottom 10pt of your text field will get cut off.

To fix this you have to give your bottom constraint a negative offset:

uidTextField.snp_makeConstraints { make in 
    make.left.equalTo(self.contentView).offset(10)
    make.right.equalTo(self.contentView)
    make.top.equalTo(self.contentView).offset(10)
    make.bottom.equalTo(self.contentView).offset(-10)
}

Or you could get the same constraints by doing this:

uidTextField.snp_makeConstraints { make in 
    make.edges.equalTo(contentView).inset(UIEdgeInsetsMake(10, 10, 10, 0))
}

When you are using the inset() way you have to use positive values for right and bottom inset.

I don't understand why SnapKit uses negative values for bottom and right. I think that's counterintuitive and a bit confusing.

EDIT: This is a little example that is working fine (I hardcoded a tableView with 3 custom cells that include a UITextField):

ViewController:

import UIKit
import SnapKit

class ViewController: UIViewController {
    let tableView = UITableView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(tableView)
        tableView.dataSource = self
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 70
        tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "CustomCell")

        tableView.snp_makeConstraints { (make) -> Void in
            make.edges.equalTo(view)
        }
    }
}

extension ViewController: UITableViewDataSource {
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath)
        return cell
    }
}

CustomTableViewCell:

import UIKit

class CustomTableViewCell: UITableViewCell {
    let textField = UITextField()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        textField.attributedPlaceholder = NSAttributedString(string: "Woo Hoo", attributes: [NSForegroundColorAttributeName:UIColor.lightGrayColor()])
        textField.textAlignment = NSTextAlignment.Left
        textField.font = UIFont.systemFontOfSize(19)
        textField.returnKeyType = UIReturnKeyType.Done
        textField.autocorrectionType = UITextAutocorrectionType.No
        contentView.addSubview(textField)

        textField.snp_makeConstraints { (make) -> Void in
            make.edges.equalTo(contentView).inset(UIEdgeInsetsMake(10, 10, 10, 0))
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
joern
  • 27,354
  • 7
  • 90
  • 105
  • Hello, sorry I did not get back to you today, however the cell is still not properly sizing when using inset rather then offset like you suggested. Same error: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead Although I do believe you are correct with the misuse of the offset. I am still looking into this – CWineland Oct 05 '15 at 16:24
  • Does your `UITextField` have a constant height? – joern Oct 05 '15 at 16:43
  • It does not, I was assuming that it would have an intrinsic or given height based on text height. I will try giving it a height – CWineland Oct 05 '15 at 17:24
  • I get an conflict in constraints error after specifying height "", "", "" – CWineland Oct 05 '15 at 17:27
  • Try overriding the system's height contraint for the contentView by giving the contentView a height constraint: `make.height.equalTo(uidTextField)` – joern Oct 05 '15 at 17:30
  • after setting the height of the content view i am getting a very similar error around conflicting constraints. one odd thing that i am noticing is that func sizeThatFits(size: CGSize) -> CGSize is being called, I was under the impression that was not called when using autolayout, there is a similar function to that for auotlayout – CWineland Oct 05 '15 at 17:49
  • I tried to reproduce the error you get, but everything is working as expected without any error. Please see my edited answer for the code I used. Maybe you are doing something differently? – joern Oct 05 '15 at 20:37