iOS 6 multiline label line spacing - ios

There is a problem with line spacing in UILabel, I am using custom font and when I use smilies there is no space between two lines. which obviously looks not so good. So I used this code for line spacing but app crashes giving the error
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSAttributedString invalid for autoresizing, it must have a single spanning paragraph style (or none) with a non-wrapping lineBreakMode.'
if ([cell.label2 respondsToSelector:#selector(setAttributedText:)])
{
UIFont *font =btMyriadProRegularWithSize14Pt;
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[paragraphStyle setLineSpacing: 22];
NSDictionary *attributes = #{ NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle };
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:chatMessage.msgString attributes:attributes];
[cell.label2 setAttributedText: attributedString];
}
else
{
NSString * msg = [NSString stringWithFormat:#"%#: %#",chatMessage.from,chatMessage.msgString];
cell.label2.text = msg;
}

try this
[cell.label2 setAdjustsFontSizeToFitWidth:NO];
maybe even only for iOS6
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) { //*
[cell.label2 setAdjustsFontSizeToFitWidth:NO];
}
detect iOS 6 as decribed here: https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/SupportingEarlieriOS.html

Set up Attributable String
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
[paragraph setLineBreakMode:NSLineBreakByWordWrapping];
[paragraph setLineBreakMode:NSLineBreakByTruncatingTail];
self.attrText = [[NSMutableAttributedString alloc] initWithString:text];
[self.attrText addAttribute:NSParagraphStyleAttributeName value:paragraph range:NSMakeRange(0, text.length)];
self.Text = text;

Related

How to just add underline below the second line of text in a Bar Button Item?

This is what I want to achieve:
I'm thinking about having two separate attributed strings and combine them together. Not sure if this is the only way?
UPDATE
The button displays "(null)" if using setAttributedTitle. It can display the right string with no attributes if using setTitle.
Still cannot display in the intended way. Any idea?
// Set current bar button attributes
NSMutableAttributedString *currentBarAttributedString = [[NSMutableAttributedString alloc] init];
[currentBarAttributedString appendAttributedString:[[NSAttributedString alloc] initWithString:#"REQUEST\n"
attributes:#{NSUnderlineStyleAttributeName: #(NSUnderlineStyleNone)}]];
[currentBarAttributedString appendAttributedString:[[NSAttributedString alloc] initWithString:#"EQUIPMENT"
attributes:#{NSUnderlineStyleAttributeName: #(NSUnderlineStyleSingle)}]];
// Initialize buttons and set titles
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
[button1 setAttributedTitle:currentBarAttributedString forState:UIControlStateNormal];
// [button1 setTitle:[currentBarAttributedString string] forState:UIControlStateNormal];
To add border to text or to change color.here is sample code which is used.
use This code in
- (void)viewDidLoad {
[super viewDidLoad];
NSString *strFirst = #"Request Equipment";
NSString *strSecond = #"Active Rentals";
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:strFirst
attributes:#{NSUnderlineStyleAttributeName: #(NSUnderlineStyleSingle),
NSForegroundColorAttributeName:[UIColor yellowColor]}]];
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:strSecond
attributes:#{NSUnderlineStyleAttributeName: #(NSUnderlineStyleNone),NSForegroundColorAttributeName:[UIColor whiteColor]}]];
//To use attribute string in button
[self.btnAttributeString setAttributedTitle:attributedString forState:UIControlStateNormal];
}
OutPut is
Please check this and let me know any issue.
Just create a NSAttributedString and format it as required
NSString *alertString = #"All heroes do not wear capes.";
NSMutableParagraphStyle* paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentLeft;
NSDictionary *attrs = #{
NSParagraphStyleAttributeName: paragraphStyle,
//provide a nsdict here with attributes you want to apply to the whole of the string.
};
NSDictionary *subAttrs = #{
NSParagraphStyleAttributeName: paragraphStyle,
//Here provide attributes for the not underlined part of the string.
};
NSDictionary *subAttrs2 = #{
NSParagraphStyleAttributeName: paragraphStyle,
//Here provide attributes for the underlined part of the string
};
//Set the range of the sub attributes.
const NSRange range = NSMakeRange(0,3);
const NSRange range2 = NSMakeRange(5,4);
NSMutableAttributedString *attributedText =
[[NSMutableAttributedString alloc] initWithString:alertString
attributes:attrs];
[attributedText setAttributes:subAttrs range:range];
[attributedText setAttributes:subAttrs2 range:range2];
Now set this attributed string as your attributed title
class UnderlinedLabel: UILabel {
override var text: String! {
didSet {
let textRange = NSMakeRange(0, count(text))
let textRange = NSMakeRange(0, text.characters.count)
let attributedText = NSMutableAttributedString(string: text)
attributedText.addAttribute(NSUnderlineStyleAttributeName , value:NSUnderlineStyle.StyleSingle.rawValue, range: textRange)
// Add other attributes if needed
self.attributedText = attributedText
}
}
}

Have multiple ranges with different attributes on NSAttributedString

I have a multiline UILabel of which I would like to increase the line height, but I also want part of it to be a different color, only the line height works fine. But as soon as I try to change the color for a certain range it just goes back to the stock appearance, no line either..
Anyone a tip? This is done in the content setter.
- (void)setContent:(NSString *)content {
_content = content;
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:self.content];
NSMutableAttributedString *mutableAttrString = [attributedString mutableCopy];
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[paragraphStyle setLineSpacing: 5.0f];
NSDictionary *attributes = #{
NSFontAttributeName: [UIFont fontWithName:#"BentonSans-Regular" size:16.0],
NSParagraphStyleAttributeName: paragraphStyle
};
NSDictionary *colorAttributes = #{
NSForegroundColorAttributeName: [UIColor redColor]
};
[mutableAttrString addAttributes:attributes range:NSRangeFromString(self.content)];
[mutableAttrString addAttributes:colorAttributes range:NSMakeRange(4, 8)];
[self.label setAttributedText: mutableAttrString];
}
Thanks!
The NSRangeFromString function expects a string like #"{3,10}". In other words, it expects a string that contains two numbers that specify the starting location and length of the range. I suspect that the content string isn't a string like that.
So this line
[mutableAttrString addAttributes:attributes range:NSRangeFromString(self.content)];
should be
[mutableAttrString addAttributes:attributes range:NSMakeRange(0,mutableAttrString.length)];
in your viewdidLoad Method assign string to self.content :
self.content = #"pass your text ";
// Remove the First line of your method it is not needed
- (void)setContent:(NSString *)content {
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:self.content];
NSMutableAttributedString *mutableAttrString = [attributedString mutableCopy];
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[paragraphStyle setLineSpacing: 5.0f];
NSDictionary *attributes = #{
NSFontAttributeName: [UIFont fontWithName:#"BentonSans-Regular" size:16.0],
NSParagraphStyleAttributeName: paragraphStyle
};
NSDictionary *colorAttributes = #{
NSForegroundColorAttributeName: [UIColor redColor]
};
[mutableAttrString addAttributes:attributes range:NSRangeFromString(self.content)];
[mutableAttrString addAttributes:colorAttributes range:NSMakeRange(4, 8)];
[self.label setAttributedText: mutableAttrString];
}

Intrinsic content size of UILabel with NSAttributedString and indentation

Why does setting an indent on the paragraph style attribute not have an affect on a UILabel using NSAttributedString?
For example:
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.firstLineHeadIndent = 50;
NSDictionary *attributes = #{
NSForegroundColorAttributeName : [UIColor redColor],
NSParagraphStyleAttributeName : paragraphStyle,
};
NSString *string = #"some string";
self.label.attributedText = [[NSAttributedString alloc] initWithString:string
attributes:attributes];
UILabel with indentation (green background set to see the label size):
UILabel without indentation (green background set to see the label size):

Cannot get a drop shadow on multiline nsstring

I'm trying to get multiline text to draw with a drop shadow without using deprecated APIs. It works fine for a single line. The relevant code looks like this:
-(void)drawRect:(CGRect)rect
{
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
paragraph.lineBreakMode = NSLineBreakByWordWrapping;
paragraph.alignment = NSTextAlignmentCenter;
UIFont *f = [UIFont systemFontOfSize:20.0];
NSMutableDictionary *attributes = [NSMutableDictionary new];
[attributes setValuesForKeysWithDictionary:#{ NSFontAttributeName : f,
NSParagraphStyleAttributeName : paragraph,
NSForegroundColorAttributeName : [UIColor blueColor] }];
NSShadow * shadow = [NSShadow new];
shadow.shadowOffset = CGSizeMake(4,4);
shadow.shadowColor = [UIColor redColor];
[attributes setValue:shadow forKey:NSShadowAttributeName];
rect.origin.y = 100;
[#"test string on one line" drawInRect:rect withAttributes:attributes];
rect.origin.y = 150;
[#"test string spanning more than one line" drawInRect:rect withAttributes:attributes];
}
and the output looks like this:
I have tested this on iPhone 5 (7.1.2), iPhone 6 (8.0), building with xCode 6. I have also tested it on the iPhone 5 when building with xCode 5.
Some more experimentation, and I discovered that the answer is to use an NSAttributedString.
While this does not show a shadow:
NSString *s = #"test string spanning more than one line"
[s drawInRect:rect withAttributes:attributes]
This does:
NSAttributedString *as = [[NSAttributedString alloc] initWithString:s attributes:attributes];
[as drawInRect:rect];
I don't think this is documented anywhere, would love to hear otherwise.

Core Text in UITableviewCell's content overlapping and repeating and superimpose on the other cells

I am using Core Text to add text to UITableviewCell's content but arabic content seems to be overlapping and repeating itself as I scroll and superimpose on the other cells.
I am also using other elements on the page which appear just fine and are not repeating . Just the Core Text seems to be repeating.
I cant figure out why .
Here is my code:
- (CTFontRef)newCustomFontWithName:(NSString *)aFontName
ofType:(NSString *)type
attributes:(NSDictionary *)attributes {
NSString *fontPath = [[NSBundle mainBundle] pathForResource:aFontName ofType:type];
NSData *data = [[NSData alloc] initWithContentsOfFile:fontPath];
CGDataProviderRef fontProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
CGFontRef cgFont = CGFontCreateWithDataProvider(fontProvider);
CGDataProviderRelease(fontProvider);
CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)attributes);
CTFontRef font = CTFontCreateWithGraphicsFont(cgFont, 0, NULL, fontDescriptor);
CFRelease(fontDescriptor);
CGFontRelease(cgFont);
return font;
}
- (CATextLayer *)customCATextLayer:(NSString *)textString {
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:24.f], (NSString *)kCTFontSizeAttribute,
[NSNumber numberWithInt:1], (NSString *)kCTLigatureAttributeName,
nil];
CTFontRef font = [self newCustomFontWithName:#"me_quranKer6"
ofType:#"ttf"
attributes:attributes];
CATextLayer *normalTextLayer = [[CATextLayer alloc] init];
normalTextLayer.font = font;
normalTextLayer.string = textString;
normalTextLayer.wrapped = YES;
normalTextLayer.foregroundColor = [[UIColor blackColor] CGColor];
normalTextLayer.fontSize = 24.f;
normalTextLayer.alignmentMode = kCAAlignmentCenter;
normalTextLayer.frame = CGRectMake(0.f, 10.f, 320.f, 32.f);
CFRelease(font);
return normalTextLayer;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
QuranVersesViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"verseCell"];
Verse *verse = [self.fetchedResultsController objectAtIndexPath:indexPath];
//English Content starts
NSMutableAttributedString * englishAttributedString;
if (!englishAttributedString)
englishAttributedString = [[NSMutableAttributedString alloc] initWithString:#""];
NSMutableAttributedString * englishSubtitleAttributedString;
NSMutableAttributedString * englishVerseAttributedString;
if (!englishVerseAttributedString)
englishVerseAttributedString = [[NSMutableAttributedString alloc] initWithString:verse.english_version];
NSMutableAttributedString * englishFootnoteAttributedString;
if (!englishFootnoteAttributedString)
englishFootnoteAttributedString = [[NSMutableAttributedString alloc] init];
NSString *englishString = #"";
if(verse.subtitle.length>0)
{
NSMutableParagraphStyle *mutParaStyle=[[NSMutableParagraphStyle alloc] init];
[mutParaStyle setAlignment:NSTextAlignmentCenter];
englishSubtitleAttributedString = [[NSMutableAttributedString alloc] initWithString:verse.subtitle];
[englishSubtitleAttributedString addAttributes:[NSDictionary dictionaryWithObject:mutParaStyle
forKey:NSParagraphStyleAttributeName]
range:NSMakeRange(0,[[englishSubtitleAttributedString string] length])];
[englishAttributedString appendAttributedString:englishSubtitleAttributedString];
[englishAttributedString addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Arial" size:30] range:NSRangeFromString(verse.subtitle)];
NSLog(#"text us %#", englishAttributedString);
}// englishString = [englishString stringByAppendingString:[NSString stringWithFormat:#"%#\n\n", verse.subtitle]];
[englishAttributedString appendAttributedString:englishVerseAttributedString];
englishString = [englishString stringByAppendingString:[NSString stringWithFormat:#"[%#:%#] %#\n", verse.whichSura.sura_no, verse.verse_no, verse.english_version]];
if(verse.footnote.length>0)
englishString = [englishString stringByAppendingString: [NSString stringWithFormat:#"\n%#\n", verse.footnote]];
englishString = [englishString stringByReplacingOccurrencesOfString:#"“" withString:#"\"" ];
englishString = [englishString stringByReplacingOccurrencesOfString:#"_" withString:#"\n" ];
cell.quranVerseEnglishTextView.attributedText = englishAttributedString;
[cell.quranVerseEnglishTextView autoResizeWithMaxWidth:MAX_TEXT_WIDTH];
cell.quranVerseEnglishTextView.backgroundColor = [UIColor clearColor];
//English Content starts
//Arabic Content
CATextLayer *arabicTextLayer = [self customCATextLayer:verse.arabic_version];
[cell.arabicView.layer addSublayer:arabicTextLayer];
return cell;
}
I was facing the same problem until I read up about NSAttributedStrings (made available in iOS 6) on this tutorial here.
The following code will solve your issue:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:#{ NSFontAttributeName : [UIFont fontWithName:#"Scheherazade" size:32], NSLigatureAttributeName: #2}];
cell.textLabel.attributedText = attributedString;
Out of curiosity, would I be correct to say that you opted to use CoreText because of difficulties in rendering embedded arabic fonts? I ventured the guess because I was attempting to use a similar method as you have done in your code when faced with that exact problem for a Quran app that I'm currently developing. If this so then I can confirm that using NSAttributedString also solves the problem. If you notice in the code above I've also set the NSLigatureAttributeName to 2 which according to the official Apple Class Reference Documentation means 'all ligatures'. Just note that this is something that I'm currently testing and I have yet to see the effects of this but I know that ligatures is a common problem in the rendering of some arabic fonts on certain platforms.
While on the subject, another common problem you may be facing is the line-spacing of arabic text and the slight overlapping of multi-line text and I've found that NSAttributedString can also be a good solution when used together with NSParagraphStyle (Hooray again for NSAttributedString!). Simply modify the above code as below:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:#{ NSFontAttributeName : [UIFont fontWithName:#"Scheherazade" size:32], NSLigatureAttributeName: #2}];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:20];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [info.text length])];
cell.textLabel.attributedText = attributedString;
Hope this helps you or anyone else out there!
EDIT - Adding this helpful post on Common Mistakes With Adding Custom Fonts to Your iOS App for reference as a "checklist" when adding custom fonts on iOS.
Actually fixed the issue myself by adding the following line in cellforRowAtIndexPath:
if (cell == nil)
{
cell = [[QuranVersesViewCell alloc] init];
.....
and also did all the initialization and setting only when the cell was nil. And MOST importantly tagged the view layer and set the text for only the matching tagged view...

Resources