Можно ли получить список атрибутов и диапазонов для NSMutableAttributedString?


Я создал метод, который принимает NSAttributedString, и я ищу, чтобы динамически создать подвид и метку, чтобы поместить строку. Поскольку атрибуты, такие как шрифт и размер, должны быть определены, чтобы правильно определить размер метки, мне нужно определить, можно ли перебирать значения и диапазоны, которые были применены к приписываемой строке?

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

7 23

7 ответов:

Apple ожидает, что вы будете использовать enumerateAttributesInRange:options:usingBlock:. Блок, который вы предоставляете, получит диапазоны и атрибуты, применимые для этого диапазона.

Я использовал это в своем коде для создания невидимых кнопок, которые помещаются за текстом, чтобы он действовал как гиперссылка.

Вы также можете использовать enumerateAttribute:inRange:options:usingBlock: Если есть только один, который вас интересует, но нет промежуточного дома, где вы могли бы быть заинтересованы, скажем, в двух атрибутах, но не в каждом атрибуте.

Swift 4

let attributedText = NSAttributedString(string: "Hello, playground", attributes: [
    .foregroundColor: UIColor.red, 
    .backgroundColor: UIColor.green, 
    .ligature: 1, 
    .strikethroughStyle: 1
])

// retrieve attributes
let attributes = attributedText.attributes(at: 0, effectiveRange: nil)

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

В случае, если вы определили attributedText метки.

Swift 3

var attributes = attributedText.attributes(at: 0, longestEffectiveRange: nil, in: NSRange(location: 0, length: attributedText.length))

Swift 2.2

var attributes = attributedText.attributesAtIndex(0, longestEffectiveRange: nil, inRange: NSMakeRange(0, attributedText.length))

Если вам нужны все атрибуты из строки во всем диапазоне, используйте следующий код:

NSDictionary *attributesFromString = [stringWithAttributes attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, stringWithAttributes.length)];

Документы Apple имеют ряд методов для доступа к атрибутам:

Чтобы получить значения атрибутов из любого типа приписываемой строки, используйте любой из следующих методов:

attributesAtIndex:effectiveRange: attributesAtIndex:longestEffectiveRange:inRange: attribute:atIndex:effectiveRange: attribute:atIndex:longestEffectiveRange:inRange: fontAttributesInRange: rulerAttributesInRange:

Swift 3:

// in case, that you have defined `attributedText` of label
var attributes = attributedText.attributes(at: 0, longestEffectiveRange: nil, in: NSMakeRange(0, attributedText.length))
...

Swift 4:

Если вы хотите получить атрибуты для NSTextAttachment (просто измените значение атрибута, если хотите шрифт)

commentTextView.attributedText.enumerateAttribute(NSAttachmentAttributeName,
                        in:NSMakeRange(0, commentTextView.attributedText.length),
                        options:.longestEffectiveRangeNotRequired) {
                        value, range, stop in
                            if let attachment = value as? NSTextAttachment {
                                print("GOT AN ATTACHMENT! for comment at \(indexPath.row)")
                            }
}

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

@IBDesignable
extension UITextField{

    @IBInspectable var placeHolderColor: UIColor? {
        get {
            if let color = self.attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor {
                return color
            }
            return nil
        }
        set {
            self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[.foregroundColor: newValue!])
        }
    }
}