NSAttributedText不适用于Swift中的UILabel

时间:2017-08-31 19:35:03

标签: swift uilabel nsattributedstring

我在iOS 10.3 iPhone 6s上使用Swift 3。

我在NSAttributedString上有一个扩展方法:

extension NSAttributedString {

    class func attributedString(title: String, titleFont: UIFont, body: String, bodyFont: UIFont) -> NSAttributedString {
        let titleAttributes = [NSFontAttributeName : titleFont]
        let bodyAttributes = [NSFontAttributeName : bodyFont]

        let title = NSAttributedString(string: "\(title): ", attributes: titleAttributes)
        let body = NSAttributedString(string: "\(body)", attributes: bodyAttributes)

        let text = NSMutableAttributedString()
        text.append(title)
        text.append(body)

        return text
    }

}

我在UITableViewCell中设置单元格时会调用此cellForRowAtIndexPath配置方法:

class MyCustomCell: UITableViewCell {

    ...

    func configure() {
        ...

        myLabel.attributedText = NSAttributedString.attributedString(title: t, titleFont: tFont, body: b, bodyFont: bFont)
    }

}

不知何故,屏幕上的标签是空白的。

参数不是可选的(换句话说,tb不是也不能为零。

如果我点按该单元格,则会打开一个屏幕,然后当我回来时,标签正确显示文字。我尝试添加{{ {1}},myLabel.setNeedsDisplay()setNeedsDisplay()等等到setNeedsLayout()方法的末尾,但没有任何效果。

我做错了什么?

其他归因字符串问题是因为人们使用常规configureNSFontAttributeName init方法之类的东西。那不是我在这里做的。

更新

如果我暂停调试器来检查UI,那么标签显示的是:

documentAttributes:

我不明白为什么它的高度为0.标签的垂直内容拥抱和内容压缩阻力优先级在故事板中设置为1000,当我使用<UILabel: 0x1041734b0; frame = (20 0; 297 0); text = 'Title: body'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x174298290>> UILabel { {1}}财产。也许垂直拥抱和压缩阻力优先级无法与属性文本一起正常工作?

更新2:

我刚刚通过将标签的垂直内容拥抱和内容压缩阻力优先级设置回默认值并为标签赋予20的高度限制来更改约束。现在标签显示正确!

我不喜欢这个解决方案,因为我希望标签在没有文字的情况下自动高度为0,如果有文字,我希望标签的高度与字体大小相匹配(可以根据不同而不同)用户偏好在我的应用中)。换句话说,我不想管理标签的高度约束。

更新3:

我在text方法中没有显示的内容...在开头我有一个configure语句,如果没有要显示的标题或正文,我会清除标签的属性文本。我的目标是隐藏标签。但是,如果有标题和正文,那么我将继续我在上面guard方法中显示的那一行。

当我在configure语句中删除此行时,标签显示为有效高度。当我使用标签的guard属性时,行为是相同的,我没有意识到。

我尝试使用textsetNeedsLayout()重新加载标签,以便在我提供文本时正确设置其大小,但它无效。

摘要

我希望能够从故事板中将垂直内容拥抱和内容压缩阻力优先级设置为1000,以便标签的高度取决于其内容。当我将标签的layoutIfNeeded()设置为nil,或“”或“Title:body”时,我希望它能够自动正确设置其高度。这可能吗?我误解了内容优先级吗?

2 个答案:

答案 0 :(得分:1)

我看到你解决了这个问题,但我想我已经把这个问题放在其他任何绊脚石的地方了。

请记住在更新UI时始终在主线程上执行此操作。当您在cellForRowAtIndexPath中重新加载单元格时,我相信您的代码是在主线程上调用的。

当你在其他地方打电话时,这样做是个好主意:

dispatchQueue.main.async {
  configure()
}

答案 1 :(得分:0)

所以事实证明我的问题是我还在configure方法的上下文之外从视图控制器调用cellForRowAtIndexPath:,并且它没有重新加载单元格&#39 ; s高度(即使我在其上设置文字后标签的高度发生了变化)。

因此,我需要添加代码以在表视图中重新加载单元格:

NSIndexPath *indexPath = ...; // Get index path for the cell I want to update.
VCInboxCell *cell = (MyCustomCell *) [self.table cellForRowAtIndexPath:indexPath];
if (cell) {
    [cell configure];
    [self.conversationsTable reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}

换句话说,我在configure中使用cellForRowAtIndexPath:设置了单元格,但此时标签的文字为零(因为该模型的数据为标签尚未设置)。然后,当模型的数据更改为标签时,我再次调用configure,但没有更新行,因此标签因为单元格中的约束而被压扁,即使它想要根据{{​​1}}(基于其文本值)的高度为19.5。

重新加载单元格会更新高度,一切都很顺利。