单元格标签中的最后一行不会出现自动布局和动态单元格高度

Last line in label for cell wont appear with auto layout and dynamic cell height

我在让我的多行标签显示其所有行时遇到了一些严重的问题。通常,标签的最后一行根本不会出现,但很明显,动态计算的单元格高度已经考虑到它应该出现,在我的中留下适当数量的白色 space细胞。

受影响的标签可以显示 1-7 行,具体取决于数据。我尝试了很多不同的限制来尝试让它显示,但不管最后一行是什么,它都不会显示。

奇怪的是,有时我进入VC时会显示,但是当我使用VC中的分段控制器显示不同的数据然后再返回时, 最后一行将再次不显示。相反的情况也经常发生(当我进入 VC 时,最后一行标签被切断,但是然后使用 VC 内的分段控制器更改显示的数据然后返回,它会然后显示正常)。

我已确保:标签设置为自动换行,行数为 0,高度大于或等于其中一行的高度,其阻力和垂直内容拥抱设置为单元格中最高的,并且宽度设置适当。

下面的代码是我如何确定标签将有多少行:

let descString = NSMutableAttributedString()

let bountyStart = NSMutableAttributedString(string: "Bounty: ", attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(15)])
let bountyDesc = NSMutableAttributedString(string: bounty.description)
descString.appendAttributedString(bountyStart)
descString.appendAttributedString(bountyDesc)

let bLine = NSMutableAttributedString(string: "\n\n", attributes: [NSFontAttributeName : UIFont.systemFontOfSize(2)])
descString.appendAttributedString(bLine)

if !(bounty.turtles == 0.0){
    let turtleStart = NSMutableAttributedString(string: "Your turtle count: ")
    let turtleAmount = NSMutableAttributedString(string: bounty.turtleCount.description)
    descString.appendAttributedString(turtleStart)
    descString.appendAttributedString(turtleAmount)
}
descriptionLabel.attributedText = descString

在下面的屏幕截图中,您可以看到正在正确计算单元格的高度,但由于某种原因,标签的最后一行拒绝显示。它应该出现在 "is for noobs" 行之后。我已经操纵白色 space 出现在行之后而不是其他地方,方法是将问题标签底部约束设置为大于或等于,并将所有其他顶部到底部约束设置为等于。

问题标签的限制条件:

我已经被这个问题难住了很长一段时间,我开始认为这不是我设置的限制,而是更深层次的东西。尽管我很想被证明是错误的。

这是我的 VC 代码。

    import UIKit

class TrendingVC: UIViewController, UITableViewDataSource, UITableViewDelegate{

    @IBOutlet weak var menubtn:UIBarButtonItem!
    @IBOutlet var trendingTableView:UITableView!  

    var trendingToggle:Int = 0
    let nwt = NWTrending()
    let appUserId = NSUserDefaults.standardUserDefaults().stringForKey("UserId") ?? "1" //@TODO: remove ?? 1
    var bountyArr: [Bounty] = []
    var compArr: [Completion] = []
    var peopleArr: [Person] = []

    var userId: String = "0"
    var username: String = ""

    let bountyCellIdentifier = "BountyCellNew"
    let personCellIdentifier = "PersonCell"
    let completedCellIdentifier = "TrendingCompletedImageCell"



    @IBAction func toggleTrending(sender:UISegmentedControl){
        switch sender.selectedSegmentIndex{
        case 0:
            //loads the bounties on segmented control tab
            trendingToggle=0
            nwt.getTrendingBounties(appUserId, position: 0){(bountyArr, err) in //@TODO: change pos
                self.bountyArr = bountyArr as [Bounty]
                self.reloadTableViewContent()
            }
        case 1:
            trendingToggle=1
            nwt.getTrendingCompletions(appUserId, position: 0){(compArr, err) in
                self.compArr = compArr as [Completion]
                self.reloadTableViewContent()
            }
        case 2:
            trendingToggle=2
            nwt.getTrendingPeople(appUserId, position: 0){(peopleArr, err) in
                self.peopleArr = peopleArr as [Person]
                self.reloadTableViewContent()
            }
        default:
            break
        }

        //reloadTableViewContent()
    }



    override func viewDidLoad() {
    super.viewDidLoad()

    trendingTableView.estimatedRowHeight = 300.0
    trendingTableView.rowHeight = UITableViewAutomaticDimension


    /******* Kyle Inserted *******/
    //for followers and following back button text, you set it here for when you segue into that section
    let backItem = UIBarButtonItem(title: " ", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
    navigationItem.backBarButtonItem = backItem
    /******* END Kyle Inserted *******/

    trendingTableView.allowsSelection = false;
    trendingTableView.delegate = self
    trendingTableView.dataSource = self

    //sidebar code
    if self.revealViewController() != nil {
        menubtn.target = self.revealViewController()
        menubtn.action = "revealToggle:"
        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

    //loads the bounty on segue
    nwt.getTrendingBounties(appUserId, position: 0){(bountyArr, err) in
        self.bountyArr = bountyArr as [Bounty]
        self.reloadTableViewContent()
    }
}


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        //deselectAllRows()

    }


    func deselectAllRows() {
        if let selectedRows = trendingTableView.indexPathsForSelectedRows() as? [NSIndexPath] {
            for indexPath in selectedRows {
                trendingTableView.deselectRowAtIndexPath(indexPath, animated: false)
            }
        }
    }

    func reloadTableViewContent() {
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.trendingTableView.reloadData()
            println("reloading table view content")
            self.trendingTableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: false)
        })
    }

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


    func tableView(trendingTableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if trendingToggle == 0{
        return bountyArr.count
        }
        else if trendingToggle == 1{
            return compArr.count
        }
        else {
            return peopleArr.count
        }
    }


    func tableView(trendingTableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        if trendingToggle == 0{
            return bountyCellAtIndexPath(indexPath)
        }
        else if trendingToggle == 1{
            return completedCellAtIndexPath(indexPath)
        }
        else{
        return personCellAtIndexPath(indexPath)
        }
    }

    //calls method to set and display each trending bounty cell
    func bountyCellAtIndexPath(indexPath:NSIndexPath) -> BountyCellNew {
        let cell = trendingTableView.dequeueReusableCellWithIdentifier(bountyCellIdentifier) as! BountyCellNew
        var bounty = bountyArr[indexPath.row]
        cell.setBountyCellTrending(bounty)
        return cell
    }

    func completedCellAtIndexPath(indexPath:NSIndexPath) -> CompletedCell{
        let cell = trendingTableView.dequeueReusableCellWithIdentifier(completedCellIdentifier) as! CompletedCell
        var comp = compArr[indexPath.row]
        cell.setTrendingCompletedCell(comp)
        return cell
    }


    func personCellAtIndexPath(indexPath:NSIndexPath) -> PersonCell{
        let cell = trendingTableView.dequeueReusableCellWithIdentifier(personCellIdentifier) as! PersonCell
        var peop = peopleArr[indexPath.row]
        cell.setTrendingPeopleCell(peop)
        return cell
    }   
}

由于代表率低,无法发表评论。 这似乎是 IB 的事情,很可能是限制条件。 确保放置在此多行 UILabel 下的任何组件的顶部约束设置为所述 UILabel.

的底部

例如,在我的这个项目中,TitleView 和 TimeAndDetailsView 都包含 UILabels 跨多行。为了让自动布局正确 space 所有约束都需要按顺序排列,还要注意 TimeAndDetails 的顶部约束是 TitleView 的底部




编辑备注: 在 tableView.reloadData() 输入以下两行之前,如果不确定,请将其放在 viewDidLoad

tableView.estimatedRowHeight = 60 //Type your cell estimated height
tableView.rowHeight = UITableViewAutomaticDimensionhere

昨晚睡着了,好的,所以我决定将您的代码添加到我之前发布的故事板图片中的详细信息标签中,它似乎显示得很好。我有几个问题和建议如下。

let descString = NSMutableAttributedString()
let bountyStart = NSMutableAttributedString(string: "Bounty: ", attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(15)])
let bountyDesc = NSMutableAttributedString(string: "this would be 'bounty.description and is set to size 40", attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(40)])
descString.appendAttributedString(bountyStart)
descString.appendAttributedString(bountyDesc)
let bLine = NSMutableAttributedString(string: "\n\n", attributes: [NSFontAttributeName : UIFont.systemFontOfSize(10)])
descString.appendAttributedString(bLine)
let turtleStart = NSMutableAttributedString(string: "Your turtle count: ")
let turtleAmount = NSMutableAttributedString(string: "random number 1234 goes here")
descString.appendAttributedString(turtleStart)
descString.appendAttributedString(turtleAmount)
detailsLabel.attributedText = descString

遗憾的是,这是在滚动视图中而不是在单元格中,因此存在第一个区别。我的第一个问题;您的 descriptionLabel.attributedText 应该显示不同的字体颜色还是 fonttypes/sizes?如果不是,那么我会说只使用 descriptionLabel.text 而不是 descriptionLabel.attributedText。 现在有白色 space 但没有任何显示的事实让我想知道 bounty.turtleCount.description 之前是否在其他地方设置为白色,或者您只是看到了您添加的换行符 \n\n 而什么也没有是因为 if !(bounty.turtles == 0.0) 没有执行。您确定执行了 if 语句吗?放置一个断点并继续操作以确保将值附加到 descString

如果这一切都是正确的,那么我的猜测仍然是有限制的。 您能否详细说明,引用您的话; "sometimes it will display when I segue in to the VC, but then when I use the segmented controller inside the VC to display different data and then go back again, the last line will again not display." 加载值和重新加载 tableview 时,您在 seg 控件中做了什么不同,导致它不显示,以及在什么条件下它在 segue 时正常工作。

我更新了 xcode,现在不再发生这种情况。