Подтвердить что ты не робот

Подчеркивание части строки с использованием NSMutableAttributedString в iOS 8 не работает

Я пытаюсь подчеркнуть часть строки, например, "строку" в строке "тестовая строка". Я использую NSMutableAttributedString, и мое решение хорошо работает на iOS7.

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]
        initWithString:@"test string"];
[attributedString addAttribute:NSUnderlineStyleAttributeName
                         value:@(NSUnderlineStyleSingle)
                         range:NSMakeRange(5, 6)];
myLabel.attributedText = attributedString;

Проблема в том, что мое решение больше не работает в iOS8. Проведя час при тестировании нескольких вариантов NSMutableAttributedString, я узнал, что это решение работает только тогда, когда диапазон начинается с 0 (длина может отличаться). В чем причина этого? Как я могу обойти это?

4b9b3361

Ответ 1

Обновление: Исследуя этот вопрос: Отображение NSMutableAttributedString на iOS 8, я наконец нашел решение!

Вы должны добавить NSUnderlineStyleNone в начале строки.

Swift 4.2 (none был удален):

let attributedString = NSMutableAttributedString()
attributedString.append(NSAttributedString(string: "test ",
                                           attributes: [.underlineStyle: 0]))
attributedString.append(NSAttributedString(string: "s",
                                           attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue]))
attributedString.append(NSAttributedString(string: "tring",
                                           attributes: [.underlineStyle: 0]))

Objective-C:

 NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
 [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"test "
                                                                          attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleNone)}]];
 [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"s"
                                                                         attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
                                                                                      NSBackgroundColorAttributeName: [UIColor clearColor]}]];
 [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"tring"]];

Еще одним бонусом такого подхода является отсутствие каких-либо диапазонов. Очень хорошо для локализованных строк.

Похоже, это ошибка Apple :(

Ответ 2

Я обнаружил, что если вы примените UnderlineStyleNone ко всей строке, вы можете выборочно применить подчеркивание к части, которая начинается посередине:

func underlinedString(string: NSString, term: NSString) -> NSAttributedString {
    let output = NSMutableAttributedString(string: string)
    let underlineRange = string.rangeOfString(term)
    output.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleNone.rawValue, range: NSMakeRange(0, string.length))
    output.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: underlineRange)

    return output
}

Ответ 3

NSMutableAttributedString *signUpString = [[NSMutableAttributedString alloc] initWithString:@"Not a member yet?Sign Up now"];

[signUpString appendAttributedString:[[NSAttributedString alloc] initWithString:@" "attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleNone)}]];

[signUpString addAttributes: @{NSForegroundColorAttributeName:UIColorFromRGB(0x43484B),NSUnderlineStyleAttributeName:[NSNumber numberWithInteger:NSUnderlineStyleSingle]} range:NSMakeRange(17,11)];

signUpLbl.attributedText = [signUpString copy];

У меня это сработало

Ответ 4

Это сентябрь 2018 года, так что этот ответ не касается iOS8, но все же касается подчеркивания части строки.

Вот расширение Swift 4, которое подчеркивает данный термин в уже составленном myAttributedString

extension NSMutableAttributedString {

    func underline(term: String) {

        guard let underlineRange = string.range(of: term) else {

            return
        }

        let startPosition = string.distance(from: term.startIndex, to: underlineRange.lowerBound)
        let nsrange = NSRange(location: startPosition, length: term.count)

        addAttribute(
            .underlineStyle,
            value: NSUnderlineStyle.styleSingle.rawValue,
            range: nsrange)
    }
}

Использование: myAttributedString.underline(term: "some term")

Ответ 5

Версия Swift 5 @Joss отвечает с небольшими изменениями, добавляя возвращаемую NSMutableAttributedString, потому что я не мог использовать исходное решение без него.

extension NSMutableAttributedString {

func underline(term: String) -> NSMutableAttributedString {
    guard let underlineRange = string.range(of: term) else {
        return NSMutableAttributedString()
    }
    let startPosition = string.distance(from: term.startIndex, to: underlineRange.lowerBound)
    let nsrange = NSRange(location: startPosition, length: term.count)
    addAttribute(
        .underlineStyle,
        value: NSUnderlineStyle.single.rawValue,
        range: nsrange)
     return self
}

}

Использование:

 let myUnderLinedText = "Hello World"
 let underLinedMutableString =  NSMutableAttributedString(string: myUnderLinedText, attributes: titleAttributes).underline(term: myUnderLinedText)

Ответ 6

Я использовал следующее расширение (используя exidy-функцию) в игровой площадке/симуляторе, и он работал нормально, вы можете изменять/добавлять атрибуты в зависимости от ваших потребностей.

 extension NSMutableAttributedString
{


    func changeWordsColour(terms:[NSString])
{
    let string = self.string as NSString
    self.addAttribute(NSForegroundColorAttributeName, value: UIColor.brownColor(), range: NSMakeRange(0, self.length))
    for term in terms
    {
        let underlineRange = string.rangeOfString(term as String)
        self.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: underlineRange)

    }
}
}

 let myStr = NSMutableAttributedString(string: "Change Words Colour")
 myStr.changeWordsColour(["change","Colour"])

Ответ 7

Добавить цвет для атрибута подчеркивания:

[attributedString addAttribute:NSUnderlineColorAttributeName
                     value:[UIColor redColor]
                     range:NSMakeRange(5, 6)];