Ios 单元格标签中的最后一行不会以自动布局和动态单元格高度显示

Ios 单元格标签中的最后一行不会以自动布局和动态单元格高度显示,ios,swift,autolayout,label,Ios,Swift,Autolayout,Label,我在让多行标签显示其所有行时遇到了一些严重问题。通常,标签的最后一行不会出现,但很明显,动态计算的单元格高度已经考虑到它应该出现,在我的单元格中留下了适当数量的空白 受影响的标签可以显示1-7行,具体取决于数据。我已经使用了许多不同的约束来尝试让它显示,但是不管最后一行是什么,它都不会显示 奇怪的是,有时当我进入VC时,它会显示出来,但当我使用VC内的分段控制器显示不同的数据,然后再次返回时,最后一行将再次不显示。相反的情况也经常发生(当我进入VC时,标签的最后一行被切断,但随后使用VC内的分段

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

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

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

我已确保的事项:标签设置为word wrap,行数为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”行之后。我已经通过将问题标签bottom to constraint设置为大于或等于,并将所有其他的top to bottom约束设置为等于,操纵了空白区域,使其显示在该行之后,而不是其他位置

问题标签的约束条件:

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

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

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

例如,在我的这个项目中,TitleView和TimeAndDetailsView都包含跨越多条线的
UILabels
。为了使autolayout能够正确地分隔所有约束,还需要注意时间和细节的顶部约束是如何位于标题视图的底部的




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

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

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

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


如果这一切都是正确的,那么我的猜测仍然是关于约束的。
请你详细说明,引用你的话;“有时,当我进入VC时,它会显示,但当我使用VC内的分段控制器显示不同的数据,然后再返回时,最后一行将再次不显示。”当加载值并重新加载tableview使其不显示时,你在seg控件中做了什么不同,在什么条件下,当您继续时,它能正常工作。

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

尝试在代码末尾的控制台
descString
中打印。并验证它在正常工作和出现错误时包含的内容。@Mindsers我有,这不是问题所在。“我的约束和自动布局”有问题“问题标签”的顶部空间下方的标签设置为等于1的距离,如果等于1则可以,只要这是标签之间所需的间距。确保“问题标签”正下方标签下的任何其他内容也对其正上方的组件具有顶部约束。对于多行
UILabel
s,如果所有内容(约束方面)都遵循故事板中的层次顺序,则效果更好。您所说的故事板中的层次顺序是什么意思?我会发布一些关于我的约束条件的图片+单元格应该是什么样子以及正在发生什么,但我没有这样做的10个声誉。我的意思是,使用我的项目作为参考。uiimageview是不相关的,因为它位于任何uilabel之前,所以我只为它的superview和height&width约束提供了一个top和left,但是,由于titleview是视图中第一个包含可以跨多行的uilabel的元素,然后,它下面的任何内容都应该对它正上方的元素具有顶部约束。TitleView底部约束设置为TimeAndDetailsView的顶部,TimeAndDetailsView的底部约束设置为top locationview。locationview底部约束是视图h中的最后一个元素
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