Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 多行UILabel-高亮显示特定范围并截断以使其可见_Ios_Objective C_Swift_Cocoa Touch_Uilabel - Fatal编程技术网

Ios 多行UILabel-高亮显示特定范围并截断以使其可见

Ios 多行UILabel-高亮显示特定范围并截断以使其可见,ios,objective-c,swift,cocoa-touch,uilabel,Ios,Objective C,Swift,Cocoa Touch,Uilabel,我目前正在我的一个应用程序中开发搜索功能,我一直在努力解决一个非常烦人的问题 假设我有以下两段文字: Lorem ipsum dolor sit amet,是一位杰出的献身者。在布朗迪特的康莫多·特里斯蒂克·莱克图斯中。维瓦摩斯·菲利斯·奥迪奥,洛雷姆·埃吉特的拉奥里特,马蒂斯·奥雷姆 尼伯埃利芬德、洛博蒂斯莫里斯a、埃格斯塔斯奥迪奥的杜伊斯 当用户执行搜索时,我将使用表视图显示结果。此表视图中的单元格显示两行文本。为了突出显示匹配的字符,我使用属性文本并设置匹配字符的粗体字体 这一切都很好。但

我目前正在我的一个应用程序中开发搜索功能,我一直在努力解决一个非常烦人的问题

假设我有以下两段文字:

Lorem ipsum dolor sit amet,是一位杰出的献身者。在布朗迪特的康莫多·特里斯蒂克·莱克图斯中。维瓦摩斯·菲利斯·奥迪奥,洛雷姆·埃吉特的拉奥里特,马蒂斯·奥雷姆

尼伯埃利芬德、洛博蒂斯莫里斯a、埃格斯塔斯奥迪奥的杜伊斯

当用户执行搜索时,我将使用表视图显示结果。此表视图中的单元格显示两行文本。为了突出显示匹配的字符,我使用属性文本并设置匹配字符的粗体字体

这一切都很好。但是,我有一个与截断相关的问题。假设用户搜索“egestas odio”。这些单词位于字符串的最末端,因此,很明显,我想显示整个字符串并截断其头部

不幸的是,我无法做到这一点。即使我为
NSMutableParagraphStyle
设置了正确的截断,我将其添加为属性字符串的属性,但它不起作用。我看到标签的开头是尾巴被截断而不是头部

我发现,如果删除所有换行符,这个问题在某种程度上得到了解决。然而,在我的情况下,这不是很实际

有人知道我如何克服这个障碍吗?或者,你可以给我一些更一般的建议,告诉我如何以稍微不同的方式实现我需要的功能。这似乎相当普遍,而且很可能有一些开源库可以帮助实现这一点。不幸的是,到目前为止我还没有找到


提前谢谢

给定一个字符串和一个您想要保留的范围,这将从任意一条边进入,直到截断的字符串符合给定的大小。您需要做额外的工作来重新计算截断字符串中的范围

Swift 4

func truncatedString(for text: String, with attributes: [NSAttributedStringKey: Any], constrainedTo size: CGSize, keeping range: Range<String.Index>?) -> String {

    let nsString = NSString(string: text)

    var nsRange = NSMakeRange(nsString.length / 2, 0)
    if let range = range {
        nsRange = NSRange(range, in: text)
    }

    var truncatedString = nsString

    let elipsis = "..."
    let elipsisWidth = elipsis.size(withAttributes: attributes).width

    var shouldAddFrontElipsis = false
    var shouldAddBackElipsis = false

    var constrainedWidthIncludingElipsis = size.width
    if nsRange.location > 0 {
        shouldAddFrontElipsis = true
        constrainedWidthIncludingElipsis -= elipsisWidth
    }

    if NSMaxRange(nsRange) < nsString.length {
        shouldAddBackElipsis = true
        constrainedWidthIncludingElipsis -= elipsisWidth
    }

    var startIndex = 0
    var endIndex = nsString.length

    while (truncatedString.boundingRect(with: CGSize(width: constrainedWidthIncludingElipsis, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: attributes, context: nil).size.height > size.height) {

        if startIndex == nsRange.location && endIndex == NSMaxRange(nsRange) {
            break
        } else {

            if startIndex < nsRange.location {
                startIndex += 1
            }

            if endIndex > NSMaxRange(nsRange) {
                endIndex -= 1
            }

            truncatedString = NSString(string: nsString.substring(with: NSMakeRange(startIndex, endIndex - startIndex)))
        }
    }

    if startIndex == 0 {
        shouldAddFrontElipsis = false
    }

    if endIndex == nsString.length {
        shouldAddBackElipsis = false
    }

    return (shouldAddFrontElipsis ? elipsis : "") + String(truncatedString) + (shouldAddBackElipsis ? elipsis : "")
}
func truncatedString(对于文本:String,具有属性:[NSAttributedStringKey:Any],约束为大小:CGSize,保留范围:range?->String{
设nsString=nsString(字符串:文本)
var nsRange=NSMakeRange(nsString.length/2,0)
如果let range=range{
nsRange=nsRange(范围,单位:文本)
}
var truncatedString=nsString
让省略“…”
让elipsisWidth=elipsis.size(withAttributes:attributes).width
var shouldAddFrontElipsis=false
var shouldAddBackElipsis=false
var constrainedWidthIncludingElipsis=size.width
如果nsRange.location>0{
shouldAddFrontElipsis=true
约束宽度,包括Elipsis-=elipsisWidth
}
如果NSMaxRange(nsRange)size.height{
如果startIndex==nsRange.location&&endIndex==NSMaxRange(nsRange){
打破
}否则{
如果startIndexNSMaxRange(nsRange){
endIndex-=1
}
truncatedString=NSString(字符串:NSString.substring(带:NSMakeRange(startIndex,endIndex-startIndex)))
}
}
如果startIndex==0{
shouldAddFrontElipsis=false
}
如果endIndex==nsString.length{
shouldAddBackElipsis=false
}
返回(shouldAddFrontElipsis?elipsis:)+字符串(截断字符串)+(shouldAddBackElipsis?elipsis:)
}

给定一个字符串和一个要保留的范围,这将从任意一条边进入,直到截断的字符串符合给定的大小。您需要做额外的工作来重新计算截断字符串中的范围

Swift 4

func truncatedString(for text: String, with attributes: [NSAttributedStringKey: Any], constrainedTo size: CGSize, keeping range: Range<String.Index>?) -> String {

    let nsString = NSString(string: text)

    var nsRange = NSMakeRange(nsString.length / 2, 0)
    if let range = range {
        nsRange = NSRange(range, in: text)
    }

    var truncatedString = nsString

    let elipsis = "..."
    let elipsisWidth = elipsis.size(withAttributes: attributes).width

    var shouldAddFrontElipsis = false
    var shouldAddBackElipsis = false

    var constrainedWidthIncludingElipsis = size.width
    if nsRange.location > 0 {
        shouldAddFrontElipsis = true
        constrainedWidthIncludingElipsis -= elipsisWidth
    }

    if NSMaxRange(nsRange) < nsString.length {
        shouldAddBackElipsis = true
        constrainedWidthIncludingElipsis -= elipsisWidth
    }

    var startIndex = 0
    var endIndex = nsString.length

    while (truncatedString.boundingRect(with: CGSize(width: constrainedWidthIncludingElipsis, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: attributes, context: nil).size.height > size.height) {

        if startIndex == nsRange.location && endIndex == NSMaxRange(nsRange) {
            break
        } else {

            if startIndex < nsRange.location {
                startIndex += 1
            }

            if endIndex > NSMaxRange(nsRange) {
                endIndex -= 1
            }

            truncatedString = NSString(string: nsString.substring(with: NSMakeRange(startIndex, endIndex - startIndex)))
        }
    }

    if startIndex == 0 {
        shouldAddFrontElipsis = false
    }

    if endIndex == nsString.length {
        shouldAddBackElipsis = false
    }

    return (shouldAddFrontElipsis ? elipsis : "") + String(truncatedString) + (shouldAddBackElipsis ? elipsis : "")
}
func truncatedString(对于文本:String,具有属性:[NSAttributedStringKey:Any],约束为大小:CGSize,保留范围:range?->String{
设nsString=nsString(字符串:文本)
var nsRange=NSMakeRange(nsString.length/2,0)
如果let range=range{
nsRange=nsRange(范围,单位:文本)
}
var truncatedString=nsString
让省略“…”
让elipsisWidth=elipsis.size(withAttributes:attributes).width
var shouldAddFrontElipsis=false
var shouldAddBackElipsis=false
var constrainedWidthIncludingElipsis=size.width
如果nsRange.location>0{
shouldAddFrontElipsis=true
约束宽度,包括Elipsis-=elipsisWidth
}
如果NSMaxRange(nsRange)size.height{
如果startIndex==nsRange.location&&endIndex==NSMaxRange(nsRange){
打破
}否则{
如果startIndexNSMaxRange(nsRange){
endIndex-=1
}
truncatedString=NSString(字符串:NSString.substring(带:NSMakeRange(startIndex,endIndex-startIndex)))
}
}
如果startIndex==0{
shouldAddFrontElipsis=false
}
如果endIndex==nsString.length{
shouldAddBackElipsis=false
}
返回(shouldAddFr