IOS: nsattributedstring

Source: Internet
Author: User

Http://iphonedevelopment.blogspot.com/2011/03/attributed-strings-in-ios.html

 

A decade ago, Apple released iPad and ios3.2. IOS developers can finally use nsattributedstring and nsmutableattributedstring. These two objects can save the strings and related fonts, paragraph formats, and formatting information together. We do not need to use the "heavyweight" uiwebview or complex CoreGraphics API to draw text.

On Mac, nsattributedstring and nsmutableattributedstring have some history in the foundation framework. Soon afterwards, app kit categorizes these two classes and adds a series of methods-Application Kit additions.
These types can be used to create formatted strings from text documents of various formats (RTF and HTML). By specifying various standard attributes and extended attributes, you can draw formatted text and calculate the size of formatted text.

In fact, the two classes are actually useful in the app kit category, rather than in the base class. Unfortunately, iossdk does not have these categories and their simplified versions. We only have these two basic classes. That is to say, we can only use the 13 Methods of nsattributedstring and the 13 Methods of nsmutableattributedstring.
In cocoa, there are "attribute" strings for "deluxe edition", while in cocoa touch, there are only common strings.

What's more strange is that nsattributedstring has an initialization method, which has a string attribute dictionary parameter, but the relevant key constant cannot be found in the header file and document published by IOS. In the overview of this document, the description of the attribute key constant used in this method exists only in the MacOSX document, but not in the IOS document.
In other words, you cannot use the initwithstring: Attributes method to create nsattributedstring or nsmutableattributedstring, because you cannot use constants used to specify the string formatting attribute. Of course, you can replace the original nsforegroundcolorattributename with the corresponding constants in coretext, for example, kctforegroundcolorattributename in core text. However, this is not recommended in the official documentation, and the NS constants and CT constants are not exactly the same (although very close ).

There is a strange situation. Apple is committed to providing underlying interfaces for complex text rendering without providing more advanced classes, so there are many features that we don't have to deal with in a more elegant way. All coretext and
CoreGraphics function (excluding core image ). However, even if Attributed String is used to implement the simplest text editing program, we still have to write a lot of underlying coretext and CoreGraphics code.

Fortunately, there is a free bridge between nsattributedstring/nsmutableattributedstring and cfattributedstringref/cfmutableattributedstringref. That is to say, you have created a cfattributedstringref, which can be converted to an nsattributedstring pointer, and then call all the methods supported by the nsattributedstring object.
Note that in iOS, uifont and ctfont are not free bridging relationships, although they are in Mac. You cannot pass a uifont as a ctfont to a function, and vice versa.

To convert uifont to ctfont, You need:

Ctfontrefctfontcreatefromuifont (uifont * font)
{
Ctfontref ctfont = ctfontcreatewithname (cfstringref) font. fontname,
Font. pointsize,
Null );
Return ctfont;
}

Note that the ctfontcreatewithname of the function contains the "Create" character, indicating that the returned ctfont will be retained. You should call cfrelease to release it to avoid Memory leakage.
It is troublesome to convert ctfont to uifont. The following is a uifont category method used to create a uifont instance from the ctfontref pointer.

@ Implementationuifont (mcutilities)
+ (ID) fontwithctfont :( ctfontref) ctfont
{
Cfstringref fontname = ctfontcopyfullname (ctfont );
Cgfloat fontsize = ctfontgetsize (ctfont );

Uifont * ret = [uifontfontwithname :( nsstring *) fontname size: fontsize];
Cfrelease (fontname );
Return ret;
}
@ End

As long as you know how to convert between ctfont and uifont, creating Attributed String is actually a simple task. The following is a nsmutableattributedstring category method. nsmutableattributedstring is created using the specified text, Font, font size, and text attributes. The result returns an Attributed String Of autorelease (the text attribute is applied to the entire string ).

+ (ID) mutableattributedstringwithstring :( nsstring *) string font :( uifont *) font color :( uicolor *) coloralignment :( cttextalignment) Alignment

{
Cfmutableattributedstringref attrstring = cfattributedstringcreatemutable (kcfallocatordefault, 0 );

If (string! = Nil)
Cfattributedstringreplacestring (attrstring, cfrangemake (0, 0), (cfstringref) string );

Cfattributedstringsetattribute (attrstring, cfrangemake (0, cfattributedstringgetlength (attrstring), kctforegroundcolorattributename, color. cgcolor );
Ctfontref thefont = ctfontcreatefromuifont (font );
Cfattributedstringsetattribute (attrstring, cfrangemake (0, cfattributedstringgetlength (attrstring), kctfontattributename, thefont );
Cfrelease (thefont );

Ctparagraphstylesetting settings [] = {kctparagraphstylespecifieralignment, sizeof (alignment), & alignment };
Ctparagraphstylerefparagraphstyle = ctparagraphstylecreate (settings, sizeof (settings)/sizeof (settings [0]);
Cfattributedstringsetattribute (attrstring, cfrangemake (0, cfattributedstringgetlength (attrstring), kctparagraphstyleattributename, paragraphstyle );
Cfrelease (paragraphstyle );


Nsmutableattributedstring * ret = (nsmutableattributedstring *) attrstring;

Return [retautorelease];
}

So annoying, why do we need to calculate the required space when drawing attributable string? But this is required. Nsattributedstring has two category methods, which are used to tell you how high the Attributed String will occupy if you specify the drawn width. Or specify the height of the painting to occupy the space of multiple widths. This is useful in text layout:
NB (1 ):This is the simplified code and the original error is corrected.
NB (2 ):In twiter, it was suggested that the calculation results of height or width be saved in ctframesetterref. Since framesetter caches the computing result, we can reuse it. If you use a new framesetter, do not create only one object, and you need to calculate the size twice. I'm going to refactor the code based on these suggestions when discussing how to draw Attributed String.

-(Cgfloat) boundingwidthforheight :( cgfloat) inheight
{
Ctframesetterrefframesetter = ctframesettercreatewithattributedstring (cfmutableattributedstringref) Self );
Cgsize suggestedsize = ctframesettersuggestframesizewithconstraints (framesetter, cfrangemake (0, 0), null, cgsizemake (cgfloat_max, inheight), null );
Cfrelease (framesetter );
Returnsuggestedsize. width;
}
-(Cgfloat) boundingheightforwidth :( cgfloat) inwidth
{
Ctframesetterrefframesetter = ctframesettercreatewithattributedstring (cfmutableattributedstringref) Self );
Cgsize suggestedsize = ctframesettersuggestframesizewithconstraints (framesetter, cfrangemake (0, 0), null, cgsizemake (inwidth, cgfloat_max), null );
Cfrelease (framesetter );
Returnsuggestedsize. height;
}

I estimate that Apple will sooner or later provide nsattributedstring uikit additions categories or other similar advanced APIs (note: the former is already provided in ios6 ). At the same time, you must deal with Attributed String. If necessary, you may need to use coretext or CoreGraphics (Apple's programming guide provides a detailed description of how to use these two frameworks to complete most common tasks ), of course, you can also encapsulate the code as a class method of nsattributedstring or nsmutableattributedstring.

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.