For this bit of code:
CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)self.fontName, self.paragraphSpacing, NULL);
[self.text insertAttributedString: [[NSAttributedString alloc] initWithString: #" \n" attributes: [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)font, (id)kCTFontAttributeName, (id)[self paragraphStyle], (id)kCTParagraphStyleAttributeName, nil]] atIndex: 0];
[self.text appendAttributedString: [[NSAttributedString alloc] initWithString: #"\n " attributes: [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)font, (id)kCTFontAttributeName, (id)[self paragraphStyle], (id)kCTParagraphStyleAttributeName, nil]]];
CFRelease(font);
For the middle two lines am getting "potential leak of an object" yet I'm not really seeing the problem.
I should mention that the static analyzer is pointing at [self paragraphStyle] which is:
- (CTParagraphStyleRef) paragraphStyle
{
CTTextAlignment alignment = self.alignment;
CGFloat lineSpacing = self.lineSpacing;
CGFloat firstLineHeadIndent = self.indent;
CGFloat headIndent = self.indent;
CGFloat tailIndent = -self.indent;
CTParagraphStyleSetting paragraphSettings[] =
{
{kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment},
{kCTParagraphStyleSpecifierLineSpacing, sizeof(lineSpacing), &lineSpacing},
{kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(firstLineHeadIndent), &firstLineHeadIndent},
{kCTParagraphStyleSpecifierHeadIndent, sizeof(headIndent), &headIndent},
{kCTParagraphStyleSpecifierTailIndent, sizeof(tailIndent), &tailIndent},
};
return CTParagraphStyleCreate(paragraphSettings, 5);
}
after the edit it becomes clear. you method is CREATING paragrah styles and those are never released
a) the method should be renamed so it becomes clearer that it creates new objects
b) you have to CFRelease them
what would be enough:
CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)self.fontName, self.paragraphSpacing, NULL);
assert(font); //may not be nil
CTParagraphStyleRef paragraph = self.paragraphStyle;
assert(paragraph); //may not be nil
[self.text insertAttributedString: [[NSAttributedString alloc] initWithString: #" \n" attributes: [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)font, (id)kCTFontAttributeName, (id)paragraph, (id)kCTParagraphStyleAttributeName, nil]] atIndex: 0];
[self.text appendAttributedString: [[NSAttributedString alloc] initWithString: #"\n " attributes: [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)font, (id)kCTFontAttributeName, (id)paragraph, (id)kCTParagraphStyleAttributeName, nil]]];
CFRelease(font);
CFRelease(paragraph); //!!!
*the asserts are bonus
Related
If I want to create some strings having format as these:
the string is the text property of a label.
some characters in this string have color different from other characters.
some characters are underlined and have a link, and when I hit the characters, and other views pop up.
Could somebody tell me how can I realize this effect?
If you support iOS < 6, better use 3rd party component e.g. TTTAttributedLabel. Else use attributedText property of UILabel.
NSDictionary *colors = [[NSDictionary alloc] initWithObjectsAndKeys: [UIColor blueColor], #"Hyd", [UIColor brownColor], #"Bang", [UIColor orangeColor], #"Delhi", [UIColor yellowColor], #"Gujarat", nil];
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:#""];
for (NSString *word in colors) {
UIColor *color = [colors objectForKey:word];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:color forKey:NSForegroundColorAttributeName];
NSAttributedString *substring = [[NSAttributedString alloc] initWithString:word attributes:attributes];
[attributeString appendAttributedString:substring];
}
As an example, say I had an array of 10 NSAttributedStrings, what is the best method for combining them all into one string? I know of the appendAttributedString method, but this only allows for one to be combined at a time, meaning a loop is needed.
Or is there any need to combine them if theyre just going into a textview - just have a loop to add them to that view? Im just trying to get my head around how a lot of text in different formats is added to a textview!
Please, try:
NSRange range = NSMakeRange(0, 1);
NSString *space = #" ";
NSMutableAttributedString *attSpace = [[NSMutableAttributedString alloc] initWithString:space];
[attSpace addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:range];
[attSpace addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"HelveticaNeue-Light"
size:11.f] range:range];
range = NSMakeRange(0, [string1 length]);
NSMutableAttributedString *att1 = [[NSMutableAttributedString alloc] initWithString:string1];
[att1 addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:range];
[att1 addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"HelveticaNeue-Light"
size:11.f] range:range];
range = NSMakeRange(0, [string2 length]);
NSMutableAttributedString *att2 = [[NSMutableAttributedString alloc] initWithString:string2];
[att2 addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:range];
[att2 addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"HelveticaNeue-Light"
size:11.f] range:range];
[att1 appendAttributedString:attSpace];
[att1 appendAttributedString:att2];
I'll share a kind of complex combination I've made mixing plain, striked and bold text in a resultant attributed string over the title of UIButton.
// Monthly button
NSMutableAttributedString *strikedOutPrice = [[NSMutableAttributedString alloc] initWithString:#"6,99"];
[strikedOutPrice setAttributes:#{ NSForegroundColorAttributeName : [UIColor whiteColor], NSStrikethroughStyleAttributeName: #2 } range:NSMakeRange(0, [strikedOutPrice length])];
NSMutableAttributedString *boldPrice = [[NSMutableAttributedString alloc] initWithString:#"4,99"];
[boldPrice setAttributes:#{ NSFontAttributeName:[UIFont boldSystemFontOfSize:16.0f], NSForegroundColorAttributeName : [UIColor whiteColor] } range:NSMakeRange(0, [boldPrice length])];
NSMutableAttributedString* titleStringMonthly = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%# %# %#" , [[LocalizationSystem sharedLocalSystem] localizedStringForKey:#"1 Month for" value:#"1 Mes por"], #"6,99", #"4,99"]];
[titleStringMonthly setAttributes:#{ NSForegroundColorAttributeName : [UIColor whiteColor] } range:NSMakeRange(0, [titleStringMonthly length])];
NSString *language = [Utils getAppLanguage];
if([language isEqualToString:#"es"])
{
[titleStringMonthly replaceCharactersInRange:NSMakeRange(10, 4) withAttributedString:strikedOutPrice];
[titleStringMonthly replaceCharactersInRange:NSMakeRange(15, 4) withAttributedString:boldPrice];
}
else
{
[titleStringMonthly replaceCharactersInRange:NSMakeRange(12, 4) withAttributedString:strikedOutPrice];
[titleStringMonthly replaceCharactersInRange:NSMakeRange(17, 4) withAttributedString:boldPrice];
}
[_oneMonthButton setAttributedTitle:titleStringMonthly forState:UIControlStateNormal];
I imagine that for this case you could have a couple of dynamic counters that keeps track of the index and length of the next range and make the replacements over a NSMutableAttributedString (like I do with my titleStringMonthly on the example)
Hope It helps someone.
You could do something like this
NSString *attr = [NSString stringWithFormat:#"%#%#%#", attributedString1, string2, string3];
Doing so will result in one attr string variable with all 10 of the strings put together, and you could do [textView setText:attr]; :)
this is what I am trying to do. I have a UILabel, but one word in that UILabel should be in a red color. After some research I found the TTTAttributedLabel
But I can't get my head arround it. Because my label is multilanguage so it's quite difficult because they are all working with NSRange.
Here is my label.
In dutch:
Het 25m bad is vandaag **bezet** van 12:00 tot 15:00
In English
The 25m pool is today **occupied** from 12:00 till 15:00
I need the text in bold in the red color.
Can anybody help me?
Kind regards
For example, you could use this snippet to get the NSRange where "occupied" or "bezet" is:
NSRange occupiedRange = [str rangeOfString:NSLocalizedString(#"occupied", #"")];
if (occupiedRange.location == NSNotFound) {
NSLog(#"Not found");
} else {
...
}
Hope the below code snippet may work for you
-(NSAttributedString*)configureToAttributedwithString:(NSString*)str
{
NSRange occupiedRange = [str rangeOfString:NSLocalizedString(#"occupied", #"")];
if (occupiedRange.location == NSNotFound)
{
NSLog(#"Not found");
NSAttributedString *attRStr = [[[NSAttributedString alloc] initWithString:str] autorelease];
return (attRStr);
}
else
{
NSString *string = [str substringToIndex:occupiedRange.location];
str = [str substringFromIndex:occupiedRange.location];
NSString *tarGetString = [str substringToIndex:occupiedRange.length];
str = [str substringFromIndex:occupiedRange.length];
CGColorRef colorRed = [[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] CGColor];
NSNumber *underline = [NSNumber numberWithInt:kCTUnderlineStyleSingle];
CTFontRef sysUITargetFont = CTFontCreateUIFontForLanguage(kCTFontUIFontEmphasizedSystem,20.0, NULL);
NSDictionary *attributesDictTarget = [NSDictionary dictionaryWithObjectsAndKeys:
(id)underline, (id)kCTUnderlineStyleAttributeName,
colorRed, (id)kCTForegroundColorAttributeName,
colorRed, (id)kCTStrokeColorAttributeName,nil];
CGColorRef colorBlack = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0] CGColor];
CTFontRef sysUIDefaultFont = CTFontCreateUIFontForLanguage(kCTFontUIFontMessage,20.0, NULL);
NSDictionary *attributesDictDefault = [NSDictionary dictionaryWithObjectsAndKeys:
colorBlack, (id)kCTStrokeColorAttributeName,nil];
NSMutableAttributedString *attMString = [[NSMutableAttributedString alloc] initWithString:string attributes:attributesDictDefault];
NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:tarGetString
attributes:attributesDictTarget];
[attMString appendAttributedString:stringToDraw];
NSAttributedString *stringRest = [[NSAttributedString alloc] initWithString:str
attributes:attributesDictDefault];
[attMString appendAttributedString:stringRest];
NSLog(#"check %#", [attMString string]);
return (attMString);
}
}
Hi I need using a couple of fonts with CTFontRef for an iPad application , I need use this method because my font is not English . so I found this code from this site
but compiler gives me some error :
CTFontRef font = CTFontCreateWithName(CFSTR("myfont"), 12,NULL);
NSMutableAttributedStringRef attrString = [[NSMutableAttributedString alloc] initWithString:textView.text];
[attrString addAttribute:(NSString*)kCTFontAttributeName
value:(id)font
range: NSMakeRange(0, textView.text.length)];
I would be grateful if you help me to solve the problem
Just see this. may be useful for you :
CTFontRef font = CTFontCreateWithName(CFSTR("GujaratiSangamMN-Bold"),12.0f, NULL);
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
(id)font, kCTFontAttributeName,
nil];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:textView.text
attributes:attrs];
The problem with your code is with the NSMutableAttributedStringRef. Use an NSMutableAttributedString instead:
NSString *myString = #"Hello World!!";
CTFontRef futura = CTFontCreateWithName( CFSTR("Futura"), 24.0, NULL);
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc]
initWithString:myString];
[attString addAttribute:(NSString *)kCTFontAttributeName
value:(id)futura
range:NSMakeRange(0, 4)];
I've got a simple object "post" that has two NSMutableArrays as properties. One is for "image" objects and the other is for "video" objects. At some point in the lifecycle of "post", I ask it for a dictionary representation of itself.
NSMutableDictionary *postDict = [post getDictionary];
-(NSMutableDictionary *)getDictionary{
NSMutableArray *imgDictArry = [NSMutableArray arrayWithObjects:nil];
NSMutableArray *movDictArry = [NSMutableArray arrayWithObjects:nil];
for (int i = 0; i<self.images.count; i++) {
NSMutableDictionary *imgDict = [[self.images objectAtIndex:i] getDictionary];
[imgDictArry addObject:imgDict];
}
for (int i = 0; i<self.videos.count; i++) {
NSMutableDictionary *movDict = [[self.videos objectAtIndex:i] getDictionary];
[movDictArry addObject:movDict];
}
NSMutableDictionary *postDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:self.friendsOnly], #"IsFriendsOnly",
self.message, #"Message",
self.shortText, #"ShortText",
self.authorId, #"AuthorId",
self.recipientId, #"RecipientId",
self.language, #"Language",
self.lat, #"Lat",
self.lng, #"Lng",
imgDictArry, #"Images",
movDictArry, #"Videos",
nil];
return postDict;
}
As you can see, the "image" and "video" objects have their own methods for describing themselves as NSMutableDictionary objects.
-(NSMutableDictionary *)getDictionary{
return [NSMutableDictionary dictionaryWithObjectsAndKeys:
self.nativeURL, #"NativeURL",
self.previewURL, #"PreviewURL",
self.smallURL, #"SmallURL",
self.thumbURL, #"ThumbURL",
self.imageId, #"ImageId",
self.width, #"Width",
self.height, #"Height",
nil];
}
I'm not getting any errors but my imgDictArry and movDictArry objects are turning out to be NULL after I've set them on the postDict object. If I log them to the console just before this moment, I can see the dictionary data. But the other classes requesting this object is getting null for those properties.
Perhaps one of your functions such as self.shortText (or self.lat...) is returning nil, in which case dictionaryWithObjectsAndKeys isn't what you expect it to be: it's truncated to the first function that returns nil...
I changed the postDict creation to this...
NSMutableDictionary *postDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:self.friendsOnly], #"IsFriendsOnly",
self.message, #"Message",
self.shortText, #"ShortText",
self.authorId, #"AuthorId",
self.recipientId, #"RecipientId",
self.language, #"Language",
self.lat, #"Lat",
self.lng, #"Lng",
nil];
[postDict setObject:imgDictArry forKey:#"Images"];
[postDict setObject:movDictArry forKey:#"Videos"];
and it's fixed. But I don't know why.