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

Posted

技术标签:

【中文标题】单元格标签中的最后一行不会出现自动布局和动态单元格高度【英文标题】:Last line in label for cell wont appear with auto layout and dynamic cell height 【发布时间】:2015-09-17 04:55:08 【问题描述】:

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

受影响的标签可以显示 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

在下面的屏幕截图中,您可以看到单元格的高度正在正确计算,但由于某种原因,标签的最后一行只是拒绝显示。它应该出现在“适合新手”行之后。通过将问题标签底部设置为大于或等于约束,并将所有其他从上到下的约束设置为等于,我已经操纵空白出现在行之后而不是其他位置。

问题标签的约束:

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

这是我的 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
       

【问题讨论】:

尝试在代码末尾的控制台descString 中打印。并验证它在什么时候工作正常以及什么时候出错。 @Mindsers 我有,这不是问题。这是我的约束和自动布局的问题 【参考方案1】:

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

例如,在我的这个项目中,TitleView 和 TimeAndDetailsView 都包含跨越多行的UILabels。为了允许自动布局适当地间隔所有约束需要按顺序排列,还要注意 TimeAndDetails 的顶部约束是 TitleView 的底部

编辑说明: 在你tableView.reloadData()之前输入以下两行,或者如果不确定,把它放在viewDidLoad

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

【讨论】:

顶部空间下方到问题标签的标签设置为等于 1 的距离 如果它等于 1 就可以了,只要这是您想要的标签之间的间距。确保“问题标签”正下方的标签下的任何其他内容也对其正上方的组件具有顶部约束。对于多行UILabels,如果一切(约束)​​都遵循故事板中的层次顺序,则更好。 故事板中的层次顺序是什么意思?我会发布一些我的限制条件的图片 + 单元格的外观与正在发生的事情,但我没有 10 名这样做的声誉。 我的意思是,使用我的项目作为参考。 uiimageview 是无关紧要的,因为它出现在任何 uilabels 之前,所以我只给它一个 top 和 left 到它的 superview 和一个 height&width 约束,但是,因为 titleview 是视图中包含可以跨越多个 uilabel 的第一个元素行,那么它下面的任何东西都应该对它上面的元素有顶部约束。 TitleView底部约束设置为TimeAndDetailsView顶部,TimeAndDetailsView底部约束设置为顶部locationview。 并且位置视图底部约束是视图中的最后一个元素,底部约束是底部布局指南【参考方案2】:

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

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 是否应该显示不同的字体颜色或字体类型/大小?如果不是,那么我会说只使用descriptionLabel.text 而不是descriptionLabel.attributedText。 现在有空白但没有向我们显示的事实让我想知道 bounty.turtleCount.description 之前是否在其他地方设置为白色,或者您只是看到您添加的换行符 \n\n 并且什么都没有,因为 if !(bounty.turtles == 0.0) 不执行.您确定执行了 if 语句吗?放置一个断点并遵循以确保将值附加到 descString 如果这一切都是正确的,那么我的猜测仍然会受到限制。 您能否详细说明,引用您的话; “有时它会在我进入 VC 时显示,但是当我使用 VC 内部的分段控制器显示不同的数据然后再返回时,最后一行将再次不显示。”在加载值并重新加载使其不显示的 tableview 时,您在 seg 控件中做了什么不同,以及在您进行 segue 时它在什么条件下正常工作。

【讨论】:

没问题。感谢您的帮助。是的,我正在显示不同的字体类型颜色和大小。不,它没有设置为白色,是的,我已经仔细检查了几次。它肯定会运行并且肯定会附着在字符串上。你可以看出细胞正在为它腾出空间,它只是没有出现。这似乎是随机的,我从另一个 VC 复制了代码,在某些 VC 中它会显示,而在其他一些则不会,有时它会在使用分段控制器时显示,有时它不会 祝您调试成功。这是关于自调整大小的单元格的最佳帖子之一,也许那里可能列出了可以解决您的问题的详细信息。 ***.com/questions/18746929/… 好吧,好吧,检查一下代码,也许我错过了一些东西(我第一次阅读你的帖子并没有意识到你在谈论细胞,哈哈),如果不是,我觉得一切都很好。只有与您的问题无关的建议是,不需要viewDidLoad 中的所有self.,您只需要闭包块中的self,如果您不添加更多部分,也无需调用numberOfSectionsInTableView,因为默认值已经是 1。出于好奇,所有 3 个单元格的高度都是 300 像素吗?您是否浏览了我发布的链接以查看是否找到了自定尺寸单元格可能缺少的任何内容? 一个单元格可以在 160-240 左右变化,一个单元格始终是 117,另一个单元格可以在 680-740 之间变化(大约)。我确实经历了它,我改变了突出的东西(估计行高度的位置),但它们似乎没有影响任何东西【参考方案3】:

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

【讨论】:

以上是关于单元格标签中的最后一行不会出现自动布局和动态单元格高度的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局约束动态调整表格视图单元格的大小

动态单元格高度的自动布局约束

自动布局动态大小 uitableview 单元格的最佳方法是啥

具有自动布局的 UITableView 中的动态单元格高度

自动布局:具有可变高度和两个标签的表格单元格

具有固定高度的表格单元格中的自动布局多行标签