NSMutableAttributedString: как получить атрибуты в диапазоне - PullRequest
0 голосов
/ 27 ноября 2018

Я создал простую игровую площадку, чтобы продемонстрировать свою проблему в получении атрибутов приписанных строк.Возможно, я не понимаю, как определить диапазоны: возможно, мне не хватает чего-то еще.

Я определил NSMutableAttributedString, в котором есть два цвета, а также изменение шрифта на жирный (для синего) и курсив(для красного):

var someText =  NSMutableAttributedString()

let blueAttri : [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12), NSAttributedString.Key.foregroundColor : UIColor.blue]
let redAttri : [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 12), NSAttributedString.Key.foregroundColor : UIColor.red]

someText = NSMutableAttributedString(string: "Some blue string here; ", attributes: blueAttri)
someText.append(NSMutableAttributedString(string: "Some red string here; ", attributes: redAttri))

На этом этапе строка выглядит хорошо, показывая текст обоими цветами.

Затем я определил 3 диапазона (пытаясь использовать разные подходы к определению диапазонов.)

var range1 = NSRange()
var range2 = NSRange(location: 0, length: someText.length)
var range3 = NSRange(location: 40, length: 44)

Наконец, я пытаюсь получить атрибуты для текста

// retrieve attributes
let attributes1 = someText.attributes(at: 0, effectiveRange: &range1)

// iterate each attribute
print("attributes1")
for attr in attributes1 {
    print(attr.key, attr.value)
}

let attributes2 = someText.attributes(at: 0, effectiveRange: &range2)

// iterate each attribute
print("attributes2")
for attr in attributes2 {
    print(attr.key, attr.value)
}


let attributes3 = someText.attributes(at: 0, effectiveRange: &range3)

// iterate each attribute
print("attributes3")
for attr in attributes3 {
    print(attr.key, attr.value)
}

Я получаю следующие результаты.Во всех случаях отображается только первый набор атрибутов.

attribute1
NSAttributedStringKey (_rawValue: NSColor) UIExtendedSRGBColorSpace 0 0 1 1
NSAttributedStringKey (_rawValue: NSFont) семейство шрифтов: ".SFMITX«;вес шрифта: полужирный;стиль шрифта: нормальный;размер шрифта: 12.00pt

attribute2
NSAttributedStringKey (_rawValue: NSColor) UIExtendedSRGBColorSpace 0 0 1 1 NSAttributedStringKey (_rawValue: NSFont) font-family: ".SFUIText-Semibold";вес шрифта: полужирный;стиль шрифта: нормальный;размер шрифта: 12.00pt

attribute3
NSAttributedStringKey (_rawValue: NSColor) UIExtendedSRGBColorSpace 0 0 1 1
NSAttributedStringKey (_rawValue: NSFont) font-family: ".SFUIText-Sem;"вес шрифта: полужирный;стиль шрифта: нормальный;font-size: 12.00pt

Что мне нужно сделать, чтобы получить все атрибуты в строке?

Было предложено использовать перечисляемые атрибуты.Это не кажется законным.См. Ниже: enter image description here

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Используя enumerateAttributes Я смог зафиксировать диапазоны курсивом (просто чтобы показать один пример).Ниже приведен полный код:

//Create Empty Dictionaries for storing results
var attributedFontRanges = [String: UIFont]()
var attributedColorRanges = [String: UIColor]()

//Find all attributes in the text.
someText.enumerateAttributes(in: NSRange(location: 0, length: someText.length)) { (attributes, range, stop) in

    attributes.forEach { (key, value) in
        switch key {

        case NSAttributedString.Key.font:
            attributedFontRanges[NSStringFromRange(range)] = value as? UIFont

        case NSAttributedString.Key.foregroundColor:
            attributedColorRanges[NSStringFromRange(range)] = value as? UIColor

        default:

            assert(key == NSAttributedString.Key.paragraphStyle, "Unknown attribute found in the attributed string")
        }
}
}

//Determine key(range) of Italic font
var italicRange = attributedFontRanges.filter { $0.value.fontName == ".SFUIText-Italic" }.keys

print("italicRange: \(italicRange)")

Выводятся следующие результаты: italicRange: ["{23, 22}"]

0 голосов
/ 27 ноября 2018

Вы используете attributes с одинаковым значением at: 0 для всех трех вызовов.Это возвращает атрибуты для 1-го символа в строке.

Если вы хотите, чтобы все атрибуты в диапазоне, использовали enumerateAttributes и передавали диапазон, который вы хотите перебрать.

Примечание. Диапазон, который вы передаете, должен основываться на кодировке строки UTF-16, а не на длине строки Swift.Эти две длины могут отличаться, если у вас есть специальные символы, такие как Emojis.Использование NSAttributedString length нормально.

...