How to make text bigger in label? - objective-c

I am wanting to use NSMutableAttributedString to change part of the original string and make part of the text bigger then the original. However, it is not working because of something very minor that I can't figure out. Here is my code:
NSString *combineString = [NSString stringWithFormat:#"%#", ...];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:combineString];
NSRange selectedRange = NSMakeRange(5, 4); // 4 characters, starting at index 22
[string beginEditing];
[string addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:50]
range:selectedRange];
[string endEditing];
mainCell.label.text = combineString;

You’re setting the text property, which takes an NSString—your attributed string, string, isn’t actually going anywhere. Try this:
mainCell.label.attributedText = string;

Related

How do I change the color of a word that was replaced from the original string?

For example, there is an NSString called "input" that converts what the user types into the text view into an NSString.
NSString *input = inputTextField.text;
So "input" depends on whatever the user types in. Now, the following code is used to change the word that the user puts, to change it into another word. This only happens after pressing a "Convert" button.
input = [input stringByReplacingOccurrencesOfString:#"(?wi)\\bHello!\\b" withString:#"greetings!" options:NSRegularExpressionSearch range:NSMakeRange(0, [input length])];
There are over 500 words that will get replaced automatically depending on what the user types in. After it goes through all the scanning, this is the code at the end. It makes the correct auto capitalization.
NSMutableString *input2 = [input mutableCopy];
NSString *pattern = #"(^|\\.|\\?|\\!|\\.\"|\\!\"|\\?\")\\s*(\\p{Letter})";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL];
[regex enumerateMatchesInString:input options:0 range:NSMakeRange(0, [input length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange r = [result rangeAtIndex:2];
[input2 replaceCharactersInRange:r withString:[[input substringWithRange:r] uppercaseString]];
}];
So you can see that the "input" is made into a copy and now becomes "input2." The replaced input is what comes out on another text view. like this:
_outputTextField.text = input2;
And this words fine. If I put, "Hello! How are you?" it will make it into "Greetings! How are you?" My problem is, on the output text view, I want that whatever word changed from the ORIGINAL writing, to become red so the user knows what changed.
I tried this, but that doesn't do anything.
NSMutableAttributedString *mutable = [[NSMutableAttributedString alloc] initWithString:input2];
[mutable addAttribute: NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, [input2 length])];
Another approach I tried is adding:
if (input != input2) {
//Above code here.
}
and inside I added the above code but it doesn't do anything. The easiest approach I see is something like this, if the input (original) doesn't match the input2, then make it change the color what doesn't match.
Create a new NSMutableAttributedString *newMAS .
Then do your parsing of the original string and append segments to the newMAS string, from either the original string, or the replacement text. At the same time you append the replacement text, also set the font attribute for that part of the NSAttributedString, using code like this:
[newMAS addAttribute:NSForegroundColorAttributeName
value:[NSColor redColor]
range:rangeOfReplacementText];
Or, you could create a NSMutableAttributedString for the replacement text and set its color as above, then just append that to newMAS as you go, interleaving segments of the original string without the attribute and this attributed replacement text, using methods to append NSString or NSAttributedString onto an NSMutableAttributedString. Useful methods include:
- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)attrString;
- (void)appendString:(NSString *)aString;
- (void)appendAttributedString:(NSAttributedString *)attrString;

How to change background only to some words in a textView

I need to change the background color of some particular words in a text that stay in a textView. Something similar to what happens in Firefox when you seearch for a word... So lets say I have a textView with this text
"A man is sitting in front of my porch and another man is calling him"
and I want to change background color to the 2 occurence of the word
"man"
... how could I do that?
I know that there is NSAttributedString to do this kind of things but I can not understand how to modify only some particular words... in the examples I found Googling it there were only examples of how to change the first 5 characters or things like this...
Try this:
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString: #"Your String"];
NSUInteger count = 0;
NSUInteger length = [attrString length];
NSRange range = NSMakeRange(0, length);
while(range.location != NSNotFound)
{
range = [[attrString string] rangeOfString:#"YOURWORD" options:0 range:range];
if(range.location != NSNotFound) {
[attrString addAttribute:NSBackgroundColorAttributeName value:YOURCOLOR range:NSMakeRange(range.location, [word length])];
range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
count++;
}
}

Custom NSFormatter in Objective C

I am trying to write my own custom formatter in Objective C by subclassing NSNumberFormatter. Specifically what I'd like to do is make a number turn red if it is above or below certain values. The apple documentation says
For example, if you want negative financial amounts to appear in red, you have this method return a string with an attribute of red text. In attributedStringForObjectValue:withDefaultAttributes: get the non-attributed string by invoking stringForObjectValue: and then apply the proper attributes to that string.
Based on this advice I implemented the following code
- (NSAttributedString*) attributedStringForObjectValue: (id)anObject withDefaultAttributes: (NSDictionary*)attr;
{
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:[self stringForObjectValue:anObject]];
if ([[attrString string] floatValue] < -20.0f) {
[attrString addAttribute:#"NSForegroundColorAttributeName" value:[NSColor redColor] range:NSMakeRange(0, 10)];
return attrString;
} else return attrString;
}
But when I test this all it does is freeze my application. Any advice would be appreciated. Thanks.
I believe this has something to do with your NSRange that you create. I believe your length (10 in your example) is out of bounds. Try getting the length of the string that you use to initialize your NSMutableAttributedString.
For example:
- (NSAttributedString*) attributedStringForObjectValue: (id)anObject withDefaultAttributes: (NSDictionary*)attr;
{
NSString *string = [self stringForObjectValue:anObject];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
NSInteger stringLength = [string length];
if ([[attrString string] floatValue] < -20.0f)
{
[attrString addAttribute:#"NSForegroundColorAttributeName" value:[NSColor redColor] range:NSMakeRange(0, stringLength)];
}
return attrString;
}
Here is how I was finally able to implement this. To make it more visible when a number is negative, I decided to make the background of the text red with white text. The following code does work in a NSTextField cell. I'm not sure why the code in my question (and the answer) does not work, addAttribute should work.
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes: (NSDictionary *)attributes{
NSString *string = [self stringForObjectValue:anObject];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
NSInteger stringLength = [string length];
if ([[attrString string] floatValue] < 0)
{
NSDictionary *firstAttributes = #{NSForegroundColorAttributeName: [NSColor whiteColor],
NSBackgroundColorAttributeName: [NSColor blueColor]};
[attrString setAttributes:firstAttributes range:NSMakeRange(0, stringLength)];
}
return attrString;
}

NSMutableAttributedStrings - objectAtIndex:effectiveRange:: Out of bounds

I'm trying to add some fancy text to a label, but I've run into some problems with the NSMutableAttributedString class. I was trying to achieve four this: 1. Change font, 2. Underline range, 3. Change range color, 4. Superscript range.
This code:
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification
{
NSMutableAttributedString* display = [[NSMutableAttributedString alloc]
initWithString:#"Hello world!"];
NSUInteger length = [[display string]length] - 1;
NSRange wholeRange = NSMakeRange(0, length);
NSRange helloRange = NSMakeRange(0, 4);
NSRange worldRange = NSMakeRange(6, length);
NSFont* monoSpaced = [NSFont fontWithName:#"Menlo"
size:22.0];
[display addAttribute:NSFontAttributeName
value:monoSpaced
range:wholeRange];
[display addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:1]
range:helloRange];
[display addAttribute:NSForegroundColorAttributeName
value:[NSColor greenColor]
range:helloRange];
[display addAttribute:NSSuperscriptAttributeName
value:[NSNumber numberWithInt:1]
range:worldRange];
//#synthesize textLabel; is in this file.
[textLabel setAttributedStringValue:display];
}
Gives me this error:
NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds
Also, I tried messing around with the ranges, but became even more confused when I tried NSRange worldRange = NSMakeRange(4, 5);. I don't understand why that produces this: Hell^o wor^ld!, where the letters inside the ^s are superscripts.
NSRange worldRange = NSMakeRange(6, 6); produces the desired effect, hello ^world!^.
What the label looks like:
Your length is too long on worldRange. NSMakeRange takes two arguments, the start point and the length, not the start point and the end point. That's probably why you are getting confused about both problems.
NSRange has two values, the start index and the length of the range.
So if you're starting at index 6 and going length characters after that you're going past the end of the string, what you want is:
NSRange worldRange = NSMakeRange(6, length - 6);

Any way to bold part of a NSString?

Is there any way to bold only part of a string?
For example:
Approximate Distance: 120m away
Thanks!
What you could do is use an NSAttributedString.
NSString *boldFontName = [[UIFont boldSystemFontOfSize:12] fontName];
NSString *yourString = ...;
NSRange boldedRange = NSMakeRange(22, 4);
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:yourString];
[attrString beginEditing];
[attrString addAttribute:kCTFontAttributeName
value:boldFontName
range:boldedRange];
[attrString endEditing];
//draw attrString here...
Take a look at this handy dandy guide to drawing NSAttributedString objects with Core Text.
As Jacob mentioned, you probably want to use an NSAttributedString or an NSMutableAttributedString. The following is one example of how you might do this.
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:#"Approximate Distance: 120m away"];
NSRange selectedRange = NSMakeRange(22, 4); // 4 characters, starting at index 22
[string beginEditing];
[string addAttribute:NSFontAttributeName
value:[NSFont fontWithName:#"Helvetica-Bold" size:12.0]
range:selectedRange];
[string endEditing];
If you do not want to bother with fonts (as not every variation of font contains "Bold"), here is another way to do this. Please be aware, this is currently only available on OS X...:
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:"Approximate Distance: 120m away"];
[attrString beginEditing];
[attrString applyFontTraits:NSBoldFontMask
range:NSMakeRange(22, 4)];
[attrString endEditing];
The code above gave me crash when I created UILabel with this attributedString.
I used this code and it worked:
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
NSRange boldedRange = NSMakeRange(0, 1);
UIFont *fontText = [UIFont systemFontOfSize:12]; //[UIFont fontWithName:#"Lato-Bold" size:12];
NSDictionary *dictBoldText = [NSDictionary dictionaryWithObjectsAndKeys:fontText, NSFontAttributeName, nil];
[attrString setAttributes:dictBoldText range:boldedRange];
Swift
Also includes getting the range of the string you want to embolden dynamically
let nameString = "Magoo"
let string = "Hello my name is \(nameString)"
let attributes = [NSFontAttributeName:UIFont.systemFontOfSize(14.0),NSForegroundColorAttributeName: UIColor.black]
let boldAttribute = [NSFontAttributeName:UIFont.boldSystemFontOfSize(14.0)]
let attributedString = NSMutableAttributedString(string: string, attributes: attributes)
let nsString = NSString(string: string)
let range = nsString.rangeOfString(nameString)
if range.length > 0 { attributedString.setAttributes(boldAttribute, range: range) }
someLabel.attributedText = attributedString
To bold a string without hardcoding its font, you can use the StrokeWidth attribute with a negative value:
let s = NSMutableAttributedString(string: "Approximate Distance: 120m away")
s.addAttribute(NSStrokeWidthAttributeName, value: NSNumber(value: -3.0), range: NSRange(22..<26))
An NSString is just a data container. It doesn't contain any details about presentation concerns.
It sounds like what you probably want to do is bold part of the UILabel that is being used to display your string. Which I don't think you can do. But you could always break the UI down into three labels, one for "Approximate Distance:", one for "120 m", and one for "away". Place them in-line with each other and you should get the desired effect.
Another option might be to use a UIWebView and a little bit of markup to display your string with embedded formatting information, as discussed here:
http://iphoneincubator.com/blog/windows-views/display-rich-text-using-a-uiwebview
In Xamarin ios you can bold part of a NSString this way:
public static NSMutableAttributedString BoldRangeOfString (string str, float fontSize, int startRange, int lengthRange)
{
var firstAttributes = new UIStringAttributes {
Font = UIFont.BoldSystemFontOfSize(fontSize)
};
NSMutableAttributedString boldString = new NSMutableAttributedString (str);
boldString.SetAttributes (firstAttributes.Dictionary, new NSRange (startRange, lengthRange));
return boldString;
}
and call this method:
myLabel = new UILabel ();
...
myLabel.AttributedText = BoldRangeOfString("my text", fontSize, startRange, lengthRange);
I coupled #Jacob Relkin and #Andrew Marin answers, otherwise, I got the crashes. Here is the answer for iOS9:
UIFont *boldFont = [UIFont boldSystemFontOfSize:12];
NSString *yourString = #"Approximate Distance: 120m away";
NSRange boldedRange = NSMakeRange(22, 4);
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:yourString];
[attrString beginEditing];
[attrString addAttribute:NSFontAttributeName
value:boldFont
range:boldedRange];
[attrString endEditing];
I took a look at the official documentation: 1 and 2.
Shorter way using Swift5+
let labelNotes = UILabel() //or UITextView(), etc...
let attributedNotes = NSMutableAttributedString(string: "Bold: some stuff not bold")
attributedNotes.addAttribute(NSAttributedString.Key.font, value: UIFont.boldSystemFont(ofSize: 14), range: NSRange(location: 0, length: 5))
labelNotes.attributedText = attributedNotes
If you don't want to hardcode the font or/and the size try this code for bolding full strings:
NSMutableAttributedString *myString = [[NSMutableAttributedString alloc] initWithString:mainString];
[myString beginEditing];
[myString addAttribute:NSStrokeWidthAttributeName
value:[[NSNumber alloc] initWithInt: -3.f]
range:NSMakeRange(0, [mainString length])];
[myString endEditing];