NSAttributedString with sub/superscript on iOS 13 [duplicate] - ios

Trying to display super/subscript text using NSAttributedString in a UITextView seems broken in iOS13 - unless anyone knows otherwise?
Curiously if I use the UIFont systemFont then it works - but if I use any other font it doesn't.
See below for my code to setup a UITextView in my test app.
- (void)viewDidLoad
{
[super viewDidLoad];
UIFont* font = [UIFont systemFontOfSize:32];
//UIFont* font = [UIFont fontWithName:#"Helvetica Neue" size:32];
//UIFont* font = [UIFont fontWithName:#"Courier" size:32];
//UIFont* font = [UIFont fontWithName:#"Arial" size:32];
NSMutableAttributedString* as = [[NSMutableAttributedString alloc] initWithString:#"Super2Script" attributes:#{NSFontAttributeName : font}];
[as addAttribute:(NSString*)kCTSuperscriptAttributeName value:#(1) range:NSMakeRange(5, 1)];
UITextView* tv = [[UITextView alloc] initWithFrame:CGRectZero];
tv.attributedText = as;
[tv sizeToFit];
[self.view addSubview:tv];
tv.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
}

Simple 'fix' for this one.
It appears kCTSuperscriptAttributeName no longer works in iOS13 (for non-system fonts.) You need to use NSSuperscriptAttributeName instead. No idea where the definition for this lives (which header) so the actual string value required is "NSSuperScript"

Related

UILabel.attributedText not show up on iPhone 4 + iOS 7.0.3

Got a iPhone 4 in the field and a strange problem, the UILabel does not show up any text. I tested it on iPhone 4S + iOS 7 simulator, it works fine.
Code:
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:[colLabel.text copy]];
[attributeString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:1]
range:(NSRange){0,[attributeString length]}];
colLabel.text = nil;
colLabel.attributedText = [attributeString copy];
colLabel.font = [UIFont boldSystemFontOfSize:12];
I have checked. Its showing on iPhone 4, there may be something else. Clean build and delete from device and run again
I have been played with the attributed text for a while, and find out something new:
It seems like on iOS 7.0.x, NSUnderlineStyleAttributeName does not play well with other attributes like color or font, once they are bundled together, it just will not show up the text. Only having underline style actually could draw the text like below:
NSAttributedString* attrStr = [[NSAttributedString alloc] initWithString:colLabel.text
attributes:#{NSUnderlineStyleAttributeName:#(NSUnderlineStyleSingle)}];
colLabel.attributedText = attrStr;
But once you add something like
colLabel.backgroundColor = [UIColor greenColor];
or
colLabel.font = [UIFont boldSystemFontOfSize:12];
It just won't show up, unless you make two changes: appended a newline character to your original string, and set the label's numberOfLines to 2.
like:
NSAttributedString* attrStr =
[[NSAttributedString alloc] initWithString:#"TEST\n" // <---
attributes:
#{NSUnderlineStyleAttributeName:#(NSUnderlineStyleSingle),
NSParagraphStyleAttributeName:paragraph}];
UILabel* myLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 0, 0)];
myLabel.backgroundColor = [UIColor greenColor];
myLabel.attributedText = attrStr;
[myLabel sizeToFit];
myLabel.numberOfLines = 2; // <---

How to display superscript % character as string in UIlabel?

How to display superscript % character as string in UIlabel? I know % does not exist in unicode as a superscript but is there is any way we can display % as a superscript instead of using html tags??
I found this post on Stackoverflow on superscript styling text using attributed string:
NSAttributedString superscript styling
So using that, I hacked up this demo:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIFont *font = [UIFont fontWithName:#"Helvetica" size:20];
UILabel *textBlock1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height / 2.0)];
textBlock1.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
textBlock1.textAlignment = NSTextAlignmentCenter;
textBlock1.font = font;
textBlock1.text = #"57%";
UILabel *textBlock2 = [[UILabel alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height / 2.0, self.view.bounds.size.width, self.view.bounds.size.height / 2.0)];
textBlock2.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
textBlock2.textAlignment = NSTextAlignmentCenter;
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:#"57%"
attributes:#{NSFontAttributeName: font}];
[attributedString setAttributes:#{NSFontAttributeName : [UIFont fontWithName:#"Helvetica" size:10]
, NSBaselineOffsetAttributeName : #10} range:NSMakeRange(2, 1)];
textBlock2.attributedText = attributedString;
[self.view addSubview:textBlock1];
[self.view addSubview:textBlock2];
}
The result:
For a simple to use Swift solution, you might want to checkout HandyUIKit. After importing it into your project (e.g. via Carthage – see instructions in README) you can do something like this:
import HandyUIKit
"57^{%}".superscripted(font: UIFont.systemFont(ofSize: 20, weight: .medium))
This line will return an NSAttributedString which will look exactly like what you're looking for. Just assign it to a UILabels attributedText property and that's it!
If you're looking for subscripting a text, simply use subscripted(font:) instead. It will recognize structures like CO_{2}. There's also superAndSubscripted(font:) if you want to combine both.
See the docs for more information and additional examples.

ios 6.0 setAttributedText crash

- (IBAction)pinFieldChanged:(id)sender {
UITextField *pinField = sender;
float kerninig = 76.0;
NSAttributedString *attributedString =
[[NSAttributedString alloc]
initWithString:pinField.text
attributes:
#{
NSFontAttributeName : [UIFont fontWithName:#"Helvetica Neue" size:36],
NSForegroundColorAttributeName : [UIColor colorWithRed:130.0/255.0 green:130.0/255.0 blue:130.0/255.0 alpha:1.0],
NSKernAttributeName : #(kerninig)
}];
if ([pinField respondsToSelector:#selector(setAttributedText:)]) {
[pinField setAttributedText:attributedString];
}
}
My app is crashing under ios6.0 when i'm trying to set attributed text to text field, though this selector is available iOS 6.0 and later
Can you give me any idea why this could happen?
Thanks in advance!)
iOS5 may be expects a CTFont so use
NSString* s = #"Yo ho ho and a bottle of rum!";
NSMutableAttributedString* mas = [[NSMutableAttributedString alloc] initWithString:s];
__block CGFloat f = 18.0;
CTFontRef basefont = CTFontCreateWithName((CFStringRef)#"Baskerville", f, NULL);
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/iOS5bookExamples/ch23p689styledText1/p579p593styleText1/RootViewController.m
use below ios 6
NSAttributedString *stringValue= [[NSAttributedString alloc] initWithString:#"cocoalibrary.blogspot.com" attributes:#{NSForegroundColorAttributeName: [UIColor redColor]}];
NSAttributedString is not available below than IOS 6. See this link, you can found this line.
In iOS 6 and later you can use attributed strings to display formatted
text in text views, text fields, and some other controls

ios 7 typography on labels and UIFont

I have the following code:
UILabel *registerLabel = [ [UILabel alloc ] initWithFrame:CGRectMake(20.0, 90.0, [self screenWidth], 43.0) ];
registerLabel.textAlignment = NSTextAlignmentLeft;
registerLabel.textColor = [UIColor whiteColor];
registerLabel.backgroundColor = [UIColor blackColor];
registerLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:(20.0)];
//registerLabel.adjustsFontSizeToFitWidth = YES;
registerLabel.text = #"Register";
But I see in some of the ios 7 demo apps (like calendar) the font is large but much thinner. I tried using Helevetica Neue Light but that doesn't work. Is there a way to make the font thinner or what font are they using?
I found the answer to be this:
registerLabel.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:(36.0)];
.font is what you need

ios Dynamic sizing labels

I've tried to search online, but haven't found a clear answer for my issue so I've come to ask for your expert advice. I have a view with 2 labels on it. The first label is used to show an abbreviation of a name, 2-3 letters. and the second label shows the full name.
The question that I have is if there was a way to dynamically size the label based on the font type, size, and string length given? I ask because I would like the second label close to the first without too much empty space between the two or without the first label overlapping the second.
The reason that this isn't all in one label is because the first label should have a bigger font and different color scheme then the second label.
Any advice is greatly appreciated.
You can calculate the size of in which your string will appear and then can set frame of your UILabel to that size see following code as a sample -
//Calculate the expected size based on the font and linebreak mode of your label
CGSize maximumLabelSize = CGSizeMake(296,9999);
CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font
constrainedToSize:maximumLabelSize
lineBreakMode:yourLabel.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;
Update -
Use sizeWithAttributes: instead, which now takes an NSDictionary. Pass in the pair with key UITextAttributeFont and your font object like this:
CGSize size = [string sizeWithAttributes:
#{NSFontAttributeName:
[UIFont systemFontOfSize:17.0f]}];
Check Replacement for deprecated sizeWithFont: in iOS 7? for more details
This will also do the trick and will take into account attributed text
label.attributedText = attrString;
CGSize maximumLabelSize = CGSizeMake(187,CGFLOAT_MAX);
CGSize requiredSize = [label sizeThatFits:maximumLabelSize];
CGRect labelFrame = label.frame;
labelFrame.size.height = requiredSize.height;
label.frame = labelFrame;
'sizeWithFont:' is deprecated: first deprecated in iOS 7.0.
so try sizeWithAttributes
- (void)viewDidLoad
{
[super viewDidLoad];
label = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, 300, 20)];
label.backgroundColor = [UIColor blueColor];
const CGFloat fontSize = 30;
UIFont *regularFont = [UIFont systemFontOfSize:fontSize];
UIColor *foregroundColor = [UIColor blackColor];
attrs = [NSDictionary dictionaryWithObjectsAndKeys:
regularFont, NSFontAttributeName,
foregroundColor, NSForegroundColorAttributeName
, nil];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]
initWithString:#"Test Text"
attributes:attrs];
[label setAttributedText:attributedText];
[self.view addSubview:label];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGSize expectedLabelSize = [label.text sizeWithAttributes:attrs]; // iOS 7 Code <--
CGRect newFrame = label.frame;
newFrame.size.width = expectedLabelSize.width;
label.frame = newFrame;
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]
initWithString:#"Longer Test Text"
attributes:attrs];
[label setAttributedText:attributedText];
}
As sizeWithFont: is deprecated in iOS 7, you need to use sizeWithAttributes (as maver explained here). In order to simplify code, you can add a method that you can reuse like this:
-(CGRect)rectForText:(NSString *)text
usingFont:(UIFont *)font
boundedBySize:(CGSize)maxSize
{
NSAttributedString *attrString =
[[NSAttributedString alloc] initWithString:text
attributes:#{ NSFontAttributeName:font}];
return [attrString boundingRectWithSize:maxSize
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
}
And make use of it
CGSize maximumLabelSize = CGSizeMake(280,9999);
UIFont *font = [UIFont systemFontOfSize:20];
CGRect titleRect = [self rectForText:post.title // <- your text here
usingFont:font
boundedBySize:maximumLabelSize];
In addition of Saurabh's answer. I had the same problem and you should add this line [yourLabel setNumberOfLines:0]; in order the whole text to be shown in X lines.

Resources