Прекратить enumerateAttribute: inRange: options: usingBlock: от вызова моего блока со значениями nil - PullRequest
3 голосов
/ 29 декабря 2010

Я вызываю следующий селектор в существующей строке NSAttributedString без диапазонов kCTFontAttributeName:

[attributedString enumerateAttribute:(NSString *) kCTFontAttributeName
                             inRange:NSMakeRange(0, [attributedString length])
                             options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
                          usingBlock:^(id value, NSRange range, BOOL *stop) {
    NSLog(@"Attribute: %@, %@", value, NSStringFromRange(range));
}];

и я получаю вывод ниже, но я ожидаю, что не получу вывод. Предложения?

Attribute: (null), {0, 27}
Attribute: (null), {27, 1}
Attribute: (null), {28, 1}
Attribute: (null), {29, 1}
Attribute: (null), {30, 1}

1 Ответ

9 голосов
/ 08 июля 2012

Краткий ответ?-enumerateAttribute:inRange:options:usingBlock: не делает того, о чем вы (или я) изначально думали.

Из названия можно предположить, что только перечисляет диапазоны получателя, которые содержат данный атрибут.Это не вариант.Он всегда перечисляет всю строку .Он вызывает блок для каждого запуска, с которым сталкивается.value, переданный в блок, устанавливается равным значению данного атрибута для этого прогона.Если текущий прогон не содержит данного атрибута, он передает nil для value.

Таким образом, для строки, которая не содержит данный атрибут, он все равно будет запускать блок, ноvalue всегда будет nil.Для строки, которая полностью покрыта данным атрибутом (с тем же значением), вы можете ожидать, что блок сработает один раз с value, равным значению этого атрибута в строке.Для строки, которая частично покрыта данным атрибутом, можно ожидать, что блок будет запускаться несколько раз, иногда с value из nil, а иногда с value, равным значению атрибута.

Надеюсь, это поможет.Мне тоже понадобилось время, чтобы взглянуть на это с правильной стороны.

...