Detener enumerateAttribute: InRange: Opciones: usingBlock: de llamar a mi bloque con valores nulos
-
13-10-2019 - |
Pregunta
Voy a llamar a la siguiente selector en una NSAttributedString
existente sin rangos kCTFontAttributeName
:
[attributedString enumerateAttribute:(NSString *) kCTFontAttributeName
inRange:NSMakeRange(0, [attributedString length])
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:^(id value, NSRange range, BOOL *stop) {
NSLog(@"Attribute: %@, %@", value, NSStringFromRange(range));
}];
y me da el resultado a continuación, pero yo esperaría obtener ninguna salida. Sugerencias?
Attribute: (null), {0, 27}
Attribute: (null), {27, 1}
Attribute: (null), {28, 1}
Attribute: (null), {29, 1}
Attribute: (null), {30, 1}
Solución
La respuesta corta? -enumerateAttribute:inRange:options:usingBlock:
no hace lo que usted (o yo, al principio) pensaba que lo hace.
Desde el nombre, es posible suponer que solamente enumera más de los rangos del receptor que contiene el atributo dado. Este no es el caso. Es siempre enumera más de la toda cadena. Se llama el bloque de cada Ejecutar que encuentra. El value
pasado en el bloque se establece en el valor del atributo especificado para esa ejecución. Si la ejecución actual no contiene el atributo dado, pasa nil
para value
.
Por lo tanto, para una cadena que no contiene el atributo dado, todavía se disparó el bloque, pero el value
siempre será nil
. Para una cadena que que está completamente cubierto por el atributo dado (con el mismo valor), se esperaría que el bloque de fuego una vez con value
siendo igual al valor de ese atributo en la cadena. Para una cadena que está parcialmente cubierto por el atributo dado, se esperaría que el bloque de disparar varias veces, a veces con un value
de nil
, y en ocasiones con una value
igual a la del atributo.
Espero que ayude. Me tomó un tiempo para mirarlo desde la dirección correcta, también.