Coder Social home page Coder Social logo

ohattributedlabel's Introduction

Depreciation warning!

Unfortunately, I no longer have time to maintain this class. Moreover, as since iOS6, UILabel now natively support NSAttributedStrings, this component is totally obsolete now (and maintaining it requires a lot of work for little benefit with recent projects all supporting iOS6+).

Note: If you are willing to take the lead and continue to make it evolve, feel free to contact me so I can give you some GIT access ton continue to maintain it.

Migrating away from OHAttributedLabel

For iOS6+ apps

If you need only to support iOS6+, you can use UILabel and its native support for NSAttributedString, and use my new OHAttributedStringAdditions pod to build your NSAttributedStrings more easily.

Note that OHAttributedLabel's NSAttributedString categories are building CoreText-only compatible strings and are not compatible with UILabel and UIKit/TextKit's handling of NSAttributedString introduced in iOS6. That's why you need to use OHAttributedStringAdditions instead.

iOS6+'s NSAttributedString and TextKit now supports a wide range of possibilities (making OHAttributedLabel useless anyway), letting you parse safe HTML, include attachements (images) and links, etc. So it even fits for advanced usages. See the example project in OHAttributedStringAdditions repository.

For very advanced usages or apps supporting iOS5 or earlier

If you still need to support iOS versions 5 or earlier, I strongly recommand the DTCoreText library by @Cocoanetics as a replacement — which is a way more complete framework that my own library and let you do much more stuff.


Table of Contents


About these classes

OHAttributedLabel

This class allows you to use a UILabel with NSAttributedStrings, in order to display styled text with various style (mixed fonts, color, size, ...) in a unique label. It is a subclass of UILabel which adds an attributedText property. Use this property, instead of the text property, to set and get the NSAttributedString to display.

Note: This class is compatible with iOS4.3+ and has been developped before the release of the iOS6 SDK (before Apple added support for NSAttributedLabel in the UILabel class itself). It can still be used with the iOS6 SDK (the attributedText property hopefully match the one chosen by Apple) if you need support for eariler iOS versions or for the additional features it provides.

This class also support hyperlinks and URLs. It can automatically detect links in your text, color them and make them touchable; you can also add "custom links" in your text by attaching an URL to a range of your text and thus make it touchable, and even then catch the event of a touch on a link to act as you wish to.

NSAttributedString and NSTextChecking additions

In addition to this OHAttributedLabel class, you will also find a category of NS(Mutable)AttributedString to ease creation and manipulation of common attributes of NSAttributedString (to easily change the font, style, color, ... of a range of the string). See the header file NSAttributedString+Attributes.h for a list of those comodity methods.

Example:

// Build an NSAttributedString easily from a NSString
NSMutableAttributedString* attrStr = [NSMutableAttributedString attributedStringWithString:txt];
// Change font, text color, paragraph style
[attrStr setFont:[UIFont fontWithName:@"Helvetica" size:18]];
[attrStr setTextColor:[UIColor grayColor]];

OHParagraphStyle* paragraphStyle = [OHParagraphStyle defaultParagraphStyle];
paragraphStyle.textAlignment = kCTJustifiedTextAlignment;
paragraphStyle.lineBreakMode = kCTLineBreakByWordWrapping;
paragraphStyle.firstLineHeadIndent = 30.f; // indentation for first line
paragraphStyle.lineSpacing = 3.f; // increase space between lines by 3 points
[attrStr setParagraphStyle:paragraphStyle];

// Change the color and bold of only one part of the string
[attrStr setTextColor:[UIColor redColor] range:NSMakeRange(10,3)];
[attrStr setTextBold:YES range:NSMakeRange(10,8)];

// Add a link to a given portion of the string
[attrStr setLink:someNSURL range:NSMakeRange(8,20)];

There is also a category for NSTextCheckingResult that adds the extendedURL property. This property returns the same value as the URL value for standard link cases, and return a formatted Maps URL for NSTextCheckingTypeAddress link types, that will open Google Maps in iOS version before 6.0 and the Apple's Maps application in iOS 6.0 and later.

OHASMarkupParsers and simple markup to build your attributed strings easily

The library also comes with very simple tag parsers to help you build NSAttributedStrings easily using very simple tags.

  • the class OHASBasicHTMLParser can parse simple HTML tags like <b> and <u> to make bold and underlined text, change the font color using <font color='…'>, etc

  • the class OHASBasicMarkupParser can parse simple markup like *bold text*, _underlined text_ and change the font color using markup like {red|some red text} or {#ff6600|Yeah}.

      // Example 1: parse HTML in attributed string
      basicMarkupLabel.attributedText = [OHASBasicHTMLParser attributedStringByProcessingMarkupInAttributedString:basicMarkupLabel.attributedText];
    
      // Example 2: parse basic markup in string
      NSAttributedString* as = [OHASBasicMarkupParser attributedStringByProcessingMarkupInString:@"Hello *you*!"];
    
      // Example 3: //process markup in-place in a mutable attributed string
      NSMutableAttributedString* mas = [NSMutableAttributedString attributedStringWithString:@"Hello *you*!"];
      [OHASBasicMarkupParser processMarkupInAttributedString:mas];
    

Note that OHASBasicHTMLParser is intended to be a very simple tool only to help you build attributed string easier: this is not intended to be a real and complete HTML interpreter, and will never be. For improvements of this feature, like adding other tags or markup languages, refer to issue #88)

UIAppearance support

The OHAttributedLabel class support the UIAppearance proxy API (available since iOS5). See selectors and properties marked using the UI_APPEARANCE_SELECTOR in the header.

This means that if you are targetting iOS5, you can customize all of your OHAttributedLabel links color and underline style to fit your application design, only in one call at the beginning of your application, instead of having to customize these for each instance.

For example, your could implement this in your application:didFinishLoadingWithOptions: delegate method to make all your OHAttributedLabel instances in your whole app display links in green and without underline instead of the default underlined blue:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [ [OHAttributedLabel appearance] setLinkColor:[UIColor colorWithRed:0.0 green:0.4 blue:0.0 alpha:1.0] ];
    [ [OHAttributedLabel appearance] setLinkUnderlineStyle:kCTUnderlineStyleNone ];
    return YES;
}

How to use in your project

There are three possible methods to include these classes in your project:

  1. Using Cocoapods:

    • add pod "OHAttributedLabel" to your Podfile
  2. Include OHAttributedLabel in your project:

    • Include the OHAttributedLabel.xcodeproj project in your Xcode4 workspace
    • Build this OHAttributedLabel.xcodeproj project once for the "iOS Device" (not the simulator) (1)
    • Add libOHAttributedLabel.a and CoreText.framework to your "Link Binary With Libraries" Build Phase of your app project.
    • Select the libOHAttributedLabel.a that has just been added to your app project in your Project Navigator on the left, and change the "Location" dropdown in the File Inspector to "Relative to Build Products" (1)
    • Add the -ObjC flag in the "Other Linker Flags" Build Setting (if not present already)
  3. Add libOHAttributedLabel.a and headers in your project

    • cd OHAttributedLabel
    • make clean && make (nb. rvm users may need to CC= && make clean && make)
    • copy the contents of the build/Release-Combined directory to you project (eg. ThirdParty/OHAttributedLabel)
    • Add libOHAttributedLabel.a and CoreText.framework to your "Link Binary With Libraries" Build Phase of your app project.
    • Add the OHAttributedLabel headers to your "Header Search Path" in Build Settings (eg. "$(SRCROOT)/ThirdParty/OHAttributedLabel/include/**")
    • Add the -ObjC flag in the "Other Linker Flags" Build Setting (if not present already)

Then in your application code, when you want to make use of OHAttributedLabel methods, you only need to import the headers with #import <OHAttributedLabel/OHAttributedLabel.h> or #import <OHAttributedLabel/NSAttributedString+Attributes.h> etc.

(1) Note: These two steps are only necessary to avoid a bug in Xcode4 that would otherwise make Xcode fail to detect implicit dependencies between your app and the lib.

For more details and import/linking troubleshooting, please see the dedicated page.

Sample code & Other documentation

There is no explicit docset or documentation of the class yet sorry (never had time to write one), but

  • The method names should be self-explanatory (hopefully) as I respect the standard ObjC naming conventions.
  • There are doxygen/javadoc-like documentation in the headers that should also help you describe the methods
  • The provided example ("AttributedLabel Example.xcworkspace") should also demonstrate quite every typical usages — including justifying the text, dynamically changing the style/attributes of a range of text, adding custom links, make special links with a custom behavior (like catching @mention and #hashtags), and customizing the appearance/color of links.

License & Credits

OHAttributedLabel is published under the MIT license. It has been created and developped by me (O.Halligon), but I'd like to thank all the contributors too, including @mattjgalloway, @stigi and @jparise among others.

ChangeLog — Revisions History

The ChangeLog is maintained as a wiki page accessible here.

Projects that use this class

Here is a non-exhaustive list of the projects that use this class (for those who told me about it) Feel free to contact me if you use this class so we can cross-reference our projects and quote your app in this dedicated wiki page!

ohattributedlabel's People

Contributors

343max avatar alisoftware avatar chrispix avatar cristianbica avatar delebedev avatar eanagel avatar ericflo avatar frizlab avatar hollance avatar infiniverse avatar jmoody avatar johntmcintosh avatar jparise avatar lprhodes avatar mattjgalloway avatar maximkhatskevich avatar nejj avatar pwightman avatar qchenqizhi avatar rsattar avatar steipete avatar stigi avatar triplef avatar williamdenniss avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ohattributedlabel's Issues

Links can still be activated with automaticallyDetectLinks=NO

When automaticallyDetectLinks is disabled, links are not detected and decorated during the styling phase. However, the link can still be activated. The issue appears to be in linkAtCharacterIndex: which does not check the automaticallyDetectLinks flag, a simple fix.

This is particularly problematic in the case where that text is actually part of a custom link that is unrelated to the URL.

Sub-pixel size from sizeThatFits causing blurriness

I was finding that when using small point sizes, and making use of sizeThatFits, fonts were looking blurry.

I tracked it down to the fact that it was calculating bounds that had sizes on sub-pixel boundaries. I'm guessing that due to the fact that it flips the rendering vertically, this was causing the text rendering to draw at a sub-pixel coordinate.

My fix is to change the last line of sizeThaFits to:

return CGSizeMake(floorf(sz.width),floorf(sz.height+1));

Does seem like a sensible fix?

label click

Hi,

Is there any way that i can make my label text clickable without affecting its formatting? On click of the label, I want to navigate to another view, but the formatting of my text should remain same as i set in attributed string.

Please help me out.

Thanks
Salman

Memory leak in setFontName

Instruments' memory leak detector shows some leaks in the sample project, seemingly from
setFontName:(NSString*)fontName size:(CGFloat)size range:(NSRange)range
when multiple fonts are set for the same attributed string.

I think those leaks are inherent to the NSAttributedString+Attributes category, as they appear in my project as well. In the example project, I have to click the '"World" in bold, 24' button a few times.

I also see leaks in drawTextInRect: and setTextAlignment.

Link detection in multiline label

Hi,

just stumbled upon this:

I have a label which I created like this

OHAttributedLabel *label = [[OHAttributedLabel alloc] initWithFrame:CGRectMake(40, 40, 400, 100)];
NSMutableAttributedString *string = [NSMutableAttributedString attributedStringWithString:@"Th\niii\ns is a test http://google.de?q=test+two"];
label.attributedText = string;
label.numberOfLines = 0;

[label addCustomLink:[NSURL URLWithString:@"http://google.com?q=test+one"] inRange:NSMakeRange(3, 8)];

When I click on http://google.de?q=test+two it opens http://google.com?q=test+one.
I'm pretty sure something isn't right in -linkAtPoint.

Some things that look suspicious:

  • The height of a line is it's ascent + its descent. In the method only the Ascent from CTLineGetTypographicBounds is used
  • The flipping of the coordinates is done in a confusing way.

I'll try to fix this and make the code a bit more readable. Maybe we can use code like this https://gist.github.com/966511 to make the flipping of coordinates more readable. (Please have a look if I made any mistake while writing those two methods :))

sizeToFit no longer works

It appears that changes to sizeThatFits have broken sizeToFit. Unclear if this was intentional or not. Reverting to the old version, below, fixes the issue.

- (CGSize)sizeThatFits:(CGSize)size {
    NSMutableAttributedString* attrStrWithLinks = [self attributedTextWithLinks];
    if (!attrStrWithLinks) return CGSizeZero;

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrStrWithLinks);
    CGFloat w = size.width;
    CGSize sz = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0,0),NULL,CGSizeMake(w,CGFLOAT_MAX),NULL);
    if (framesetter) CFRelease(framesetter);
    return CGSizeMake(sz.width,sz.height+1); // take 1pt of margin for security
}

One-line text disappears inside UITableView

Hello,

My app is using OHAttributedLabel in UITableView. I am loading my cell from XIB which has OHAttributedLabel.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"ImageCommentCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    OHAttributedLabel *commentLabel;
    CGRect labelFrame;

    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"ImageCommentCell" owner:self options:nil];
        cell = _imageCommentCell;
        _imageCommentCell = nil;
    }

    commentLabel = (OHAttributedLabel *)[cell viewWithTag:2];
    labelFrame = commentLabel.frame;
    labelFrame.size.height = 18;
    commentLabel.frame = labelFrame;
    commentLabel.attributedText = [NSAttributedString attributedStringWithString:@"test"];
    [commentLabel setNeedsDisplay];

    return cell;
}

My table loads fine initially (with "test" text in each cell). But when I scroll up and down the "test" text suddenly disappears in some cells. If I comment out the following code then everything works fine:

labelFrame = commentLabel.frame;
labelFrame.size.height = 18;
commentLabel.frame = labelFrame;

But I still need a way to setup the height dynamically for each label (depending on the size of text).

Thanks,
Andrey

Leak in -setFontFamily:size:bold:italic:range:

In the event that aFont is returned as nil the code as it stands will leak desc so you need to add a release in that case.

   CTFontDescriptorRef desc = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attr);
   if (!desc) return;
   CTFontRef aFont = CTFontCreateWithFontDescriptor(desc, size, NULL);
   if (!aFont) {
           CFRelease(desc);
           return;
   }

uilabel example

Hello .. I was wondering if you could provide an example of how to attach the attributed string to a uilabel. I've been trying and I keep getting the error :

error: request for member 'attributedText' in something not a structure or union

Thanks

Tappable/Linking text

I used the OHAttributedLabel to color different parts of my string. Although the tapping/linking element of the OHAttributedLabel would be great for future development for my app, I currently do not want this feature. Is there a way to turn off linking with an OHAttributedLabel?
Basically whenever i tap the text, i get an error at link in point.

thanks for any suggestions!

sizeThatFits/sizeToFit does not return the correct width (with fix)

The sizeThatFits: method of OHAttributedLabel currently returns the with of the size argument that it is passed rather than the width of the string.

- (CGSize)sizeThatFits:(CGSize)size {
    NSMutableAttributedString* attrStrWithLinks = [self attributedTextWithLinks];
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrStrWithLinks);
    CGFloat w = size.width;
    CGSize sz = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0,0),NULL,CGSizeMake(w,CGFLOAT_MAX),NULL);
    if (framesetter) CFRelease(framesetter);
    return CGSizeMake(w,sz.height+1); // take 1pt of margin
}

This can be easily fixed as follows:

- (CGSize)sizeThatFits:(CGSize)size {
    NSMutableAttributedString* attrStrWithLinks = [self attributedTextWithLinks];
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrStrWithLinks);
    CGSize sz = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0,0),NULL,CGSizeMake(size.width,CGFLOAT_MAX),NULL);
    if (framesetter) CFRelease(framesetter);
    return CGSizeMake(sz.width,sz.height+1); // take 1pt of margin
}

too tall font disappears

It seems that if the font size of attributedText is too large (the font height exceeds the height of the frame) the text fails to display at all. This was unexpected. I assumed too large text would display at least partially. The text disappears even if clipsToBounds is set to NO.

Please ignore if this is a feature or if I have spent too little time understanding how it works.

Memory Leak occurring when setting text alignment

When applying a Text Alignment value against an OHAttributedLabel, I am finding that I am getting small memory leaks for each time I am setting it. In some views, I am setting it for six or seven separate labels, meaning the number of leaks corresponds equally to the number of OHAttributedLabels.

Running instruments, I see that the leak traces back to the method:

'''
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode range:(NSRange)range {
// kCTParagraphStyleAttributeName > kCTParagraphStyleSpecifierAlignment
CTParagraphStyleSetting paraStyles[2] = {
{.spec = kCTParagraphStyleSpecifierAlignment, .valueSize = sizeof(CTTextAlignment), .value = (const void_)&alignment},
{.spec = kCTParagraphStyleSpecifierLineBreakMode, .valueSize = sizeof(CTLineBreakMode), .value = (const void_)&lineBreakMode},
};
CTParagraphStyleRef aStyle = CTParagraphStyleCreate(paraStyles, 2);
[self addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)aStyle range:range];
CFRelease(aStyle);
}
'''

found in NSAttributedString+Attributes.m.

Using Instruments, I am tracing this leak to line 153 of this file.

This line reads as CTParagraphStyleRef aStyle = CTParagraphStyleCreate(paraStyles, 2)

Below is a snippet of my code, where I set the alignment to justify for the field. I've only been playing with this module of code for a day, so I can accept that there is something I am doing wrong on my side.

NSMutableAttributedString   *attrStr                = [NSMutableAttributedString attributedStringWithString:speil_body];                    
OHAttributedLabel *speil_paragraph  = [[OHAttributedLabel alloc] init];
speil_paragraph.attributedText      = attrStr;
speil_paragraph.font                = [UIFont systemFontOfSize:SPEIL_FONT_SIZE];
speil_paragraph.backgroundColor     = [UIColor clearColor];
speil_paragraph.lineBreakMode       = UILineBreakModeWordWrap;
speil_paragraph.textAlignment       = UITextAlignmentJustify;

I will add more to this report, as I investigate further

UILineBreakModeTailTruncation doesn't work properly when resize

OHAttributedLabel does not add (...) mark at the end when some of my text if truncated.

I created an OHAttributedLabel, set UILineBreakModeTailTruncation, put an attributed string.
When I change the label frame, bug found: I do not see an (...) mark at the end of the label.

Anyone suggest sth that can fix this?

Label must have minimum height of 18?

First of all, thanks for open-sourcing this project! It's been a big timesaver.

In the project i'm working on now, it seems that if an OHAttributedLabel has a height <= 17, the label's text won't show up. I haven't been able to replicate this in the demo project yet though.

Any hint on why this may be happening?

Always in bold face when the text is Chinese

No matter what CTFontUIFontType I set to the attributed string, as long as the string is Chinese, the text will be showed in bold. I don't know if other language has the same problem.

Phone Number Links

In addition to standard URLs, I had a need for auto-detecting phone number links on devices that support calling. I decided to add it in as an optional addition to auto-detecting URLs, for easy customization:

In OHAttributedLabel.h I added two properties:

@property(nonatomic, assign) BOOL automaticallyDetectURLLinks; //!< Defaults to YES, only takes effect if automaticallyDetectLinks is YES
@property(nonatomic, assign) BOOL automaticallyDetectPhoneLinks; //!< Defaults to YES if device can make phone calls (i.e, iPhone), NO otherwise (i.e., iPad); only takes effect if automaticallyDetectLinks is YES

Then in OHAttributedLabel.m I added an internal method to return the types of links that should be auto-detected:

-(NSTextCheckingTypes)autoDetectLinkTypes
{
    NSTextCheckingTypes linkTypes = 0;
    if (self.automaticallyDetectURLLinks)
        linkTypes = linkTypes | NSTextCheckingTypeLink;
    if (self.automaticallyDetectPhoneLinks)
        linkTypes = linkTypes | NSTextCheckingTypePhoneNumber;
    return linkTypes;
}

This is used in both attributedTextWithLinks and linkAtCharacterIndex when creating the NSDataDetector. And then when the touch ends we need to do the proper action:

    if (activeLink.resultType == NSTextCheckingTypeLink)
    {   
        // we can check on equality of the links themselfes since the data detectors create new results
        if (activeLink.URL && [activeLink.URL isEqual:linkAtTouchesEnded.URL]) {
            BOOL openLink = (delegate && [delegate respondsToSelector:@selector(attributedLabel:shouldFollowLink:)])
            ? [delegate attributedLabel:self shouldFollowLink:activeLink] : YES;
            if (openLink) [[UIApplication sharedApplication] openURL:activeLink.URL];
        }
    }
    else if (activeLink.resultType == NSTextCheckingTypePhoneNumber)
    {
        // we can check on equality of the links themselfes since the data detectors create new results
        if (activeLink.phoneNumber && [activeLink.phoneNumber isEqualToString:linkAtTouchesEnded.phoneNumber]) {
            BOOL openLink = (delegate && [delegate respondsToSelector:@selector(attributedLabel:shouldFollowLink:)])
            ? [delegate attributedLabel:self shouldFollowLink:activeLink] : YES;
            if (openLink) [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"tel:%@", activeLink.phoneNumber]]];
        }
    }

Finally, we should have an intelligent initialization in commonInit:

    automaticallyDetectLinks = YES;
    automaticallyDetectURLLinks = YES;
    automaticallyDetectPhoneLinks = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel:555-555-5555"]];

I haven't extensively tested this addition, but it seems to work well for my immediate needs.

Crash on tap

Hi!

I'm getting crashes every time a user taps onto a OHAttributedLabel whether it contains links, several fonts or nothing special. Links do work properly though and don't make the app crash.

// Add the title label.
OHAttributedLabel *titleLabel = [[OHAttributedLabel alloc] initWithFrame:CGRectMake(0, 0, 200, 3)];
NSString* titleText = [dictionary objectForKey:SERVER_API_ACTIVITY_UPDATE_TITLE_KEY];
NSMutableAttributedString* attributedTitleText = [NSMutableAttributedString attributedStringWithString:titleText];
[attributedTitleText setFont:[UIFont fontWithName:@"Helvetica" size:13]];
[attributedTitleText setFont:[UIFont fontWithName:@"Helvetica-Bold" size:13] range:[titleText rangeOfString:[dictionary objectForKey:SERVER_API_ACTIVITY_UPDATE_USER_KEY]]];
[titleLabel addCustomLink:[NSURL URLWithString:@"http://www.foodreporter.net/dish/list"] inRange:[titleText rangeOfString:@"thread"]];
[attributedTitleText setTextColor:[UIColor blackColor]];
titleLabel.attributedText = attributedTitleText;
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeWordWrap;
[view addSubview:titleLabel];
[titleLabel release];

When I tap on anything in the OHAttributedLabel except on the link, I get this error and crash:
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.2.1 (8C148)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).

OHAttributedLabel.m line 264 in the linkAtPoint method:
CFIndex nbLines = CFArrayGetCount(lines); >> Program received signal: "EXEC_BAD_ACCESS".

Any direction on how to fix this?

Gon
ps: I love the way this library works with a range! Super handy.

ohattributedlabel changes position?

Hi there,
First of all, thanks for the time saving component. It works wonderfully, except for something that i have noticed.

For example I have set a ohattributedlabel, with a frame let's say - 0,20,320,50 - i wanted it on top and i have status bar visible. So the "20" should accommodate for the top status bar.
On the first look it is absolutely as expected, displays fine.
But when change to a different tab and come back the label moves lower, may be - 0,40,320,50 - and i have no idea why. Am not doing an re-drawing or anything.

The creation of the label is inside viewDidLoad method.

How can i fix this? Is there something that i am missing?

Thanks
Veeru

Using OHAttributedLabel in custom cell disturbing other code

Hello,

I am trying to use OHAttributedLabel in my custom cell. It works great as for as Attributed string part is concerned. But at the same time, it disturbs my previous functionality. Let me explain my issue...

I defined some code in my didSelectRowAtIndexPath class, which navigates to the view having details of the selected table cell (on clicking/tapping the cell contents). This code worked fine before I started using OHAttributedLabel. But now every time I click the cell contents, it only makes the cell contents bolder instead of navigating to next view.
I am stuck on the issue. Please let me know how to modify the classes such that it should still fire didSelectRowAtIndexPath method the way it did prevoiusly.

Any help is highly appreciated.
Thanks

Salman

i got 26 apple mach-o linker error

NSAttributedString+Attributes.h and .m
OHAttributedLabel.h and .m were added.
after that, the CoreText framework is added.
when I try to build the project
these error is shown

Undefined symbols for architecture armv7:
"_kCTFontFamilyNameAttribute", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontFamily:size:bold:italic:range:] in NSAttributedString+Attributes.o
"_CTFrameDraw", referenced from:
-[OHAttributedLabel drawTextInRect:] in OHAttributedLabel.o
"_CTFontCreateWithFontDescriptor", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontFamily:size:bold:italic:range:] in NSAttributedString+Attributes.o
"_CTLineGetStringRange", referenced from:
_CTLineContainsCharactersFromStringRange in OHAttributedLabel.o
"_CTLineGetTypographicBounds", referenced from:
_CTLineGetTypographicBoundsAsRect in OHAttributedLabel.o
(maybe you meant: _CTLineGetTypographicBoundsAsRect)
"_CTRunGetTypographicBounds", referenced from:
_CTRunGetTypographicBoundsAsRect in OHAttributedLabel.o
(maybe you meant: _CTRunGetTypographicBoundsAsRect)
"_kCTFontTraitsAttribute", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontFamily:size:bold:italic:range:] in NSAttributedString+Attributes.o
"_CTRunGetStringRange", referenced from:
_CTRunGetTypographicBoundsAsRect in OHAttributedLabel.o
_CTRunContainsCharactersFromStringRange in OHAttributedLabel.o
"_CTFontCopyFullName", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setTextBold:range:] in NSAttributedString+Attributes.o
"_CTLineGetOffsetForStringIndex", referenced from:
_CTRunGetTypographicBoundsAsRect in OHAttributedLabel.o
"_kCTUnderlineStyleAttributeName", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setTextUnderlineStyle:range:] in NSAttributedString+Attributes.o
"_CTFontCreateCopyWithSymbolicTraits", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setTextBold:range:] in NSAttributedString+Attributes.o
"_CTLineGetGlyphRuns", referenced from:
-[OHAttributedLabel drawActiveLinkHighlightForRect:] in OHAttributedLabel.o
"_CTFrameGetLines", referenced from:
-[OHAttributedLabel linkAtPoint:] in OHAttributedLabel.o
-[OHAttributedLabel drawActiveLinkHighlightForRect:] in OHAttributedLabel.o
"_kCTFontSymbolicTrait", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontFamily:size:bold:italic:range:] in NSAttributedString+Attributes.o
"_CTFramesetterCreateWithAttributedString", referenced from:
-[NSAttributedString(OHCommodityConstructors) sizeConstrainedToSize:fitRange:] in NSAttributedString+Attributes.o
-[OHAttributedLabel drawTextInRect:] in OHAttributedLabel.o
"_CTFrameGetLineOrigins", referenced from:
-[OHAttributedLabel linkAtPoint:] in OHAttributedLabel.o
-[OHAttributedLabel drawActiveLinkHighlightForRect:] in OHAttributedLabel.o
"_CTParagraphStyleCreate", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setTextAlignment:lineBreakMode:range:] in NSAttributedString+Attributes.o
"_kCTParagraphStyleAttributeName", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setTextAlignment:lineBreakMode:range:] in NSAttributedString+Attributes.o
"_CTFontCreateWithName", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontName:size:range:] in NSAttributedString+Attributes.o
"_CTFramesetterCreateFrame", referenced from:
-[OHAttributedLabel drawTextInRect:] in OHAttributedLabel.o
"_CTFontDescriptorCreateWithAttributes", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontFamily:size:bold:italic:range:] in NSAttributedString+Attributes.o
"_kCTFontAttributeName", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontName:size:range:] in NSAttributedString+Attributes.o
-[NSMutableAttributedString(OHCommodityStyleModifiers) setFontFamily:size:bold:italic:range:] in NSAttributedString+Attributes.o
-[NSMutableAttributedString(OHCommodityStyleModifiers) setTextBold:range:] in NSAttributedString+Attributes.o
"_CTLineGetStringIndexForPosition", referenced from:
-[OHAttributedLabel linkAtPoint:] in OHAttributedLabel.o
"_CTFramesetterSuggestFrameSizeWithConstraints", referenced from:
-[NSAttributedString(OHCommodityConstructors) sizeConstrainedToSize:fitRange:] in NSAttributedString+Attributes.o
-[OHAttributedLabel drawTextInRect:] in OHAttributedLabel.o
"_kCTForegroundColorAttributeName", referenced from:
-[NSMutableAttributedString(OHCommodityStyleModifiers) setTextColor:range:] in NSAttributedString+Attributes.o
ld: symbol(s) not found for architecture armv7
collect2: ld returned 1 exit status

please help me :(

Cannot activate link within a truncation character

This may be an issue with CoreText, and probably will not affect many people. However, for our purposes it was necessary to find a workaround since we are using OHAttributedLabel to render fixed-width columns of links with truncation.

For example, tapping the … if this were in an OHAttributedLabel would not fire the link:
Visit AliSoft…e GitHub!

The problem is that CTLineGetStringIndexForPosition gives an index of either 0 or 1 when linkAtPoint: is given a point corresponding to a truncation character like the ubiquitous … ellipsis. This is not entirely mysterious since the ellipsis is not actually in the string and may represent multiple character indices, but there does not seem to be any documentation specifying what output to expect and why.

Both 0 and 1 are valid indices, but only for the first line. After validating that the click is inside the current line, we added a test like this to determine if the position reported for the line is wrong based on the line's range in the attributed string:

CFRange range = CTLineGetStringRange(line);
CFIndex idx = CTLineGetStringIndexForPosition(line, relativePoint);
if (idx < range.location) {
  // Fix invalid index
}

Before this workaround, all taps over a truncation character anywhere in the list would activate the link at index 0 or 1 in the string. For our purposes, I simply choose a position in the line based on its range that is guaranteed to be in the link. Another option might be to test horizontally adjacent points until a link is hit. That may not be a general-purpose solution, and this issue report is more to offer awareness of the issue than to request any general fix.

Right / Center alignment

Setting alignment to UITextAlignmentCenter results in text being right aligned, and UITextAlignmentRight results in center aligned text. Looking at the code, it appears that the alignment value is cast from UITextAlignment to CTTextAlignment, which could explain the mixup - see enums below:

typedef enum {
UITextAlignmentLeft = 0,
UITextAlignmentCenter,
UITextAlignmentRight, // could add justified in future
} UITextAlignment;

enum
{
kCTLeftTextAlignment = 0,
kCTRightTextAlignment = 1,
kCTCenterTextAlignment = 2,
kCTJustifiedTextAlignment = 3,
kCTNaturalTextAlignment = 4
};
typedef uint8_t CTTextAlignment;

Error in dealloc

In xOS 5 beta, dealloc has an error that crashes the app. We release textFrame and then call [super dealloc], which must call [self setNeedsDisplay], which calls [self resetTextFrame], which releases the textFrame again.

It's easily fixed by changing this
if (textFrame) CFRelease(textFrame);
to this
if (textFrame)
{
CFRelease(textFrame);
textFrame = NULL;
}
In dealloc.

Single line label will not full justify

When creating a simple single line label, the text within it will not fully justify. The text of the label is justified just like any single-line paragraph or the last line of a paragraph: it is left justified rather than having a line run that is significantly shorter than the frame extend out with a lot of spaces between the words and letters. Doing full justify on a single line of text or the last line of a paragraph is called force-justify.

I am trying to set up a single-line label using OHAttributedLabel, but even with the alignment property set to UITextAlignmentJustify, it remains left-justified because it is a single line of text. Is there a way to force-justify a single line label? Even if the text in the label is significantly shorter than the width of the label, in this case I actually want the text to expand with spaces between the words and so on so that the first letter in the label is on the left margin and the last character is on the right margin.

Does Not want the link to open in Safari…

Hi Ali,
I have used OHAttributedLabel and it is working well.
But the problem is when i click,the link opens with Safari. I want it to be opened using a web view (Created already).
So can you tell me where should i suppose to make changes to do that?

Thanks,
Rahul

UILineBreakMode*Truncation modes (leading/trailing "…") and multiline

Word Wrapping and Truncation is not well managed.

Today the OHAttributed does not support both multiline (numberOfLines>1) and "Truncation" lineBreakMode alltogether : if you choose one of the UILineBreakMode*Truncation mode, only the first line will be displayed.

It is probably easy to add the UILineBreakModeTailTruncation mode support by using the VisibleStringRange information (I just don't have time to add this right now)

enumerator block changing textLinks

I am implementing a custom UITableViewCell and it has an updateCell method that is called from cellForRowAtIndexPath.

In -(NSMutableAttributedString*)attributedTextWithLinks there is an enumerator block that loops the custom links and sets the color and underline. It seems that when drawRect is called on the cell this blocks runs.

I now experience that the my app crashes as I scroll, I think it is due to the block changing the text attributes for cells that are off screen and as it returns and finds the cell has changes. It will choke on the Range for setTextColor being the Range from a previous cell. I am having a hard time debugging it as blocks don't disclose who "owns" them.

sizeThatFits bug

The last line of sizeThatFits has a typo:

Current:
return CGSizeMake(sz.height,sz.height+1); // take 1pt of margin for security

Should be:

return CGSizeMake(sz.width,sz.height+1); // take 1pt of margin for security

Using OHAttributedLabel inside a UITableViewCell will cause scrolling not smooth

Hi,

I am using OHAttributedLabel inside a UITableViewCell like this :

// *********************
CustomTableViewCell cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell==nil)
{
cell=[[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.attributedLabel.attributedText=[NSAttributedString attributedStringWithString:@"test"];
// *
***********************
but It will make UITableView scroll not smooth.

Do I miss something or using OHAttributedLabel in wrong way ?

Please help me out.

Thanks a lot.
Alan

Using OHAttributedLabel inside a UITableViewCell

Greetings! Is there anything extra I need to do to use attributed labels inside table view cells?

I'm using black color text with a bold system font for starters. When the cells are displayed, the label text is not visible. If I set the label's background color to something besides white, the label appears as if it's just one pixel tall ... except the frame (92, 20, 187, 64) suggests otherwise!

Last character of link not tappable

When a text is created a link using addCustomLink:inRange: method, the text becomes link correctly. However, when the last character of the text is tapped, it is not detected as tap on the link.

You can easily see this problem if you run the AttributeLabel example in simulator and tap the last character of any link.

Customize internalLink style

Hi,
I'm trying to have internal Link like the one in the example styled differently than regular http links.
But if I do [attrStr setTextColor:[UIColor redColor] range:[txt rangeOfString:@TXT_LINK]]
The color for the link and style is always the regular underlined blue.
Is it possible to style some link (internal in my case) differently?
Thanks

adjustsFontSizeToFitWidth not working?

Why is it that the adjustsFontSizeToFitWidth is not working?

OHAttributedLabel *lbl = [[[OHAttributedLabel alloc] initWithFrame:aCGRect] autorelease];
lbl.numberOfLines = 1;
lbl.backgroundColor = [UIColor clearColor];
lbl.adjustsFontSizeToFitWidth = YES;
lbl.text = strVar;

NSMutableAttributedString* attrStr = [lbl.attributedText mutableCopy];
[attrStr setTextColor:phone.textColor];
[attrStr setFont:aFont];
[attrStr addAttribute:(NSString*)kCTUnderlineStyleAttributeName value:[NSNumber numberWithInt:kCTUnderlineStyleSingle|kCTUnderlinePatternSolid] range:[name.text rangeOfString:name.text]];
lbl.attributedText = attrStr;
[attrStr release];

[cell addSubview:lbl];

automaticallyAddLinksForType should default to None

Hello,

I think OHAttributedLabel should by default behave like UILabel. Therefore it should not automatically add links. Additional behavior should rather be opt-in than opt-out.

Looking forward to the discussion :)

Best,
Ullrich

Outline text

Hi! I'm appreciate with your job.

I needed some outline text supporting for your label.

So I added some lines to your code.

  • (void)drawTextInRect:(CGRect)aRect
    {
    if (_attributedText) {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);

    // flipping the context to draw core text
    // no need to flip our typographical bounds from now on
    CGContextConcatCTM(ctx, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f));
    
    if (self.shadowColor) {
        CGContextSetShadowWithColor(ctx, self.shadowOffset, 0.0, self.shadowColor.CGColor);
    }
    
    NSMutableAttributedString* attrStrWithLinks = [self attributedTextWithLinks];
    if (self.highlighted && self.highlightedTextColor != nil) {
        [attrStrWithLinks setTextColor:self.highlightedTextColor];
    }
    if (textFrame == NULL) {
        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrStrWithLinks);
        drawingRect = self.bounds;
        if (self.centerVertically || self.extendBottomToFit) {
            CGSize sz = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0,0),NULL,CGSizeMake(drawingRect.size.width,CGFLOAT_MAX),NULL);
            if (self.extendBottomToFit) {
                CGFloat delta = MAX(0.f , ceilf(sz.height - drawingRect.size.height)) + 10 /* Security margin */;
                drawingRect.origin.y -= delta;
                drawingRect.size.height += delta;
            }
            if (self.centerVertically) {
                drawingRect.origin.y -= (drawingRect.size.height - sz.height)/2;
            }
        }
        if (self.outlineColor) {
            UIColor *textColor = self.textColor;
            CGContextSetLineWidth(ctx, self.outlineWidth);
            CGContextSetTextDrawingMode(ctx, kCGTextStroke);
            CGContextSetLineJoin(ctx, kCGLineJoinRound);
            self.textColor = self.outlineColor;
            CGMutablePathRef path = CGPathCreateMutable();
            CGPathAddRect(path, NULL, drawingRect);
            textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0,0), path, NULL);
            CGPathRelease(path);
            CTFrameDraw(textFrame, ctx);
            CGContextSetTextDrawingMode(ctx, kCGTextFill);
            self.textColor = textColor;
        }
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddRect(path, NULL, drawingRect);
        textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0,0), path, NULL);
        CGPathRelease(path);
        CFRelease(framesetter);
    }
    
    // draw highlights for activeLink
    if (activeLink) {
        [self drawActiveLinkHighlightForRect:drawingRect];
    }
    
    CTFrameDraw(textFrame, ctx);
    
    CGContextRestoreGState(ctx);
    

    } else {
    [super drawTextInRect:aRect];
    }
    }

Although this works, but i don't know that is a good method.
I hope you to add outline text next version.
Sorry for my poor English.

Use of 3rdParty fonts

Hi, great work so far.

I'm encountering crashes while trying to use some non-iOS fonts.

According to Frank Zheng's blog some work has to be done with CoreText (usually done for us with UIFont).

If I replace this line:
CTFontRef aFont = CTFontCreateWithName((CFStringRef)fontName, size, NULL);
with this one:
CTFontRef font = CTFontCreateWithName(CFSTR("myOwnFontName"), fontSize,NULL);
my code works.

But here the font name is hardcoded, I'm still looking for a way to use the fontName given to the method.

Help would be appreciated.

Thanks.


Never mind, I opened this issue too fast.
The custom font name and the name of the file were different.
Found this using NSLog(@"%@",[UIFont familyNames]);.

Sorry for the inconvenience.

CTFontCreateWithName leaks...

You need to release fonts created with CTFontCreate with CFRelease
For example in:

-(void)setFontName:(NSString*)fontName size:(CGFloat)size range:(NSRange)range {
  // kCTFontAttributeName
  CTFontRef aFont = CTFontCreateWithName((CFStringRef)fontName, size, NULL);
  [self addAttribute:(NSString*)kCTFontAttributeName value:(id)aFont range:range];
}

Crash in attributedTextWithLinks when _attributedText is nil

attributedTextWithLinks will throw an exception if _attributedText is nil. Modification of the conditional avoids this

-(NSMutableAttributedString *)attributedTextWithLinks {
    NSMutableAttributedString *str = [_attributedText mutableCopy];
        if ((str!=nil) && (self.automaticallyDetectLinks)) {

'numberOfLines' property is ignored

In UILabel there is a property named numberOfLine.
If this property set, Label text is automatically truncated if above specified line limit. (blah blah ...)
It'll be more helpful if numberOfLines property also work with OHAttributedLabel-
Can you handle this?
Thanks -

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.