简体   繁体   English

如何限制Swift中String或属性String中的字符数

[英]How to limit the number of characters in a String or attributed String in Swift

Given is a (html) String with x-number of characters. 给定是一个带有x个字符的(html)字符串。 The String will get formatted into an attributed String. String将被格式化为属性String。 Then displayed in a UILabel . 然后显示在UILabel

The UILabel has a height of >= 25 and <= 50 to limit the number of lines to 2. UILabel的高度>= 25<= 50以将行数限制为2。

Since the String has characters not visible in the formatted attributed String, like <b> / <i> , the best approach would be to limit the character count of the attributed String. 由于String具有在格式化的属性String中不可见的字符,例如<b> / <i> ,因此最好的方法是限制属性String的字符数。

UILabel property .lineBreakMode = .byTruncatingTail causes words to get cut. UILabel属性.lineBreakMode = .byTruncatingTail导致单词被删除。

在此输入图像描述

The goal , in case the character count would exceed the limit of space in the UILabel , is to cut between words . 我们的目标 ,如果字符数将超过在空间限制UILabel ,是词与词之间进行切割 Desired maxCharacterCount = 50 . 期望的maxCharacterCount = 50 Determine the last space before maxCharacterCount . 确定maxCharacterCount之前的最后一个space Cut the String and append ... as last characters of the UILabel . 剪切字符串并附加...作为UILabel最后一个字符。

What's the best approach to limit the characters? 限制角色的最佳方法是什么? Help is very appreciate. 帮助非常感谢。

Start with the full string and the known two-line height of the label and its known width, and keep cutting words off the end of the string until, at that width, the string's height is less than the label's height. 从完整的字符串和标签的已知双线高度及其已知宽度开始,并在字符串末端保留切割字,直到在该宽度处,字符串的高度小于标签的高度。 Then cut one more word off the end for good measure, append the ellipsis, and put the resulting string into the label. 然后在末尾再剪一个单词以获得良好的度量,附加省略号,并将结果字符串放入标签中。

In that way, I got this: 就这样,我得到了这个:

在此输入图像描述

Notice that the word after "time" never starts; 请注意,“时间”之后的单词永远不会开始; we stop at a precise word-end with the inserted ellipsis. 我们用插入的省略号停在一个精确的单词结尾处。 Here's how I did that: 这是我如何做到的:

    lab.numberOfLines = 2
    let s = "Little poltergeists make up the principle form of material " +
        "manifestation. Now is the time for all good men to come to the " +
        "aid of the country."
    let atts = [NSFontAttributeName: UIFont(name: "Georgia", size: 18)!]
    let arr = s.components(separatedBy: " ")
    for max in (1..<arr.count).reversed() {
        let s = arr[0..<max].joined(separator: " ")
        let attrib = NSMutableAttributedString(string: s, attributes: atts)
        let height = attrib.boundingRect(with: CGSize(width:lab.bounds.width, 
                                                      height:10000),
                                         options: [.usesLineFragmentOrigin],
                                         context: nil).height
        if height < lab.bounds.height {
            let s = arr[0..<max-1].joined(separator: " ") + "…"
            let attrib = NSMutableAttributedString(string: s, attributes: atts)
            lab.attributedText = attrib
            break
        }
    }

It is of course possible to be much more sophisticated about what constitutes a "word" and in the conditions for measurement, but the above demonstrates the general common technique for this sort of thing and should suffice to get you started. 当然,可能是什么构成了一个“字”,用于测量的情况复杂得多 ,但上述说明了一般常用的技术为这样的事情,应该足以让你开始。

try this: 试试这个:

import UIKit

class ViewController: UIViewController {
var str = "Hello, playground"
var thisInt = 10
@IBOutlet weak var lbl: UILabel!
var lblWidth : CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    lblWidth = lbl.bounds.width

    while str.characters.count <= thisInt - 3 {
        str.remove(at: str.index(before: str.endIndex))
        str.append("...")
    }
    lbl.text = str
}

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


}

string width calculation link 字符串宽度计算链接

Just for the record Matt's answer is correct, but you can remove any possible issues by creating your own subclass of UILabel which will store original value in variable. 只是为了记录Matt的答案是正确的,但你可以通过创建自己的UILabel子类来删除任何可能的问题,它将原始值存储在变量中。 Than you can update its layout from view controller when the orientation was changed. 比方向更改时,您可以从视图控制器更新其布局。

Quick correction to Mikael Weiss 's answer. 快速纠正Mikael Weiss的回答。

if str.count > thisInt +3{
    while str.count >= thisInt {
        str.remove(at: str.index(before: str.endIndex))
    }
    str.append("...")
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM