UILabel text as html text - objective-c

I am stack with a small issue.
I need to use a sentence which will have first two words bold and last two words italic.
like I am using an Objective C Developer.
How to do that. Is this possible in Objective C?
Regards,

For iOS7 you can use this:
NSString * htmlString = #"<html><body> Some html string </body></html>";
NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
UILabel * myLabel = [UILabel alloc] init];
myLabel.attributedText = attrStr;

Apple recommends that for small amounts of styled text, you should use a web view, and display the text marked up in HTML and formatted with CSS, etc.
Personally I've never taken that advice, as I would consider a UI full of web views to be a bit over kill.
There is the Core Text framework, if you want a little more control over your text and want to use attributed strings.
It isn't a one-liner though. Using core text requires quite a lot of code.
I have written a core text view that will display tappable URL links inline with text, but I have not given it arbitrary formatting support. If you're interested in showing links within text, then check it out: https://github.com/jasarien/CoreTextHyperlinkView
You may be interested in Oliver Drobnik's rich text view, which is based on Core Text too. As far as I know, you can feed it HTML and it'll produce a native view containing your formatted text. Very useful. It can be found here: https://github.com/Cocoanetics/DTCoreText

I've written a very small class called THMultiPartLabel to help me accomplish this sort of thing - you can find it on GitHub here. It's based heavily on Jason's answer to a similar question here. Using this class, you'd implement your example like so:
UIFont *normal = [UIFont systemFontOfSize:20];
UIFont *bold = [UIFont boldSystemFontOfSize:20];
UIFont *italic = [UIFont italicSystemFontOfSize:20];
NSArray *fonts = [NSArray arrayWithObjects: normal, bold, normal, italic, normal nil];
THMultiPartLabel *mpLabel = [[THMultiPartLabel alloc] initWithOffsetX:0 Y:0 defaultFonts:fonts];
[mpLabel updateText:#"I ", #"am using ", #"an ", #"Objective C ", "Developer", nil];

You should have a look at Core Text.
Here are some useful resources:
Befriending Core Text on Cocoanetics.com
Core Text Reference Collection - official Apple documentation
SimpleTextInput - Example app by Apple
CoreTextPageViewer - Example app by Apple

You can't do both with the standard UILabel implementation. But you can do one or the other.
myLabel.font = [UIFont fontWithName:#"TrebuchetMS-Bold" size:18];

Your best option is probably to replace the UILabel with a UIWebView and use HTML to do the formatting.
[EDIT]
If you have lots of them and think there is too much of a performance hit, you can (from iOS 3.2 onwards) also consider NSAttributedString, although that will be a lot more coding.

Since iOS 6 you can use NSAttributedString with an UILabel, a NSAttributedString takes a NSString as an argument in one of its contructors, after that you can specify which ranges of this string has a particular text style.
You can find a good example on how to do it on iOS 6 here: http://weblog.invasivecode.com/post/31931916393/introduction-to-nsattributedstring-for-ios-6
If you what something backwards compatible, I'm strongly recommend the OHAttributedLabel which can be found here: https://github.com/AliSoftware/OHAttributedLabel
Note: OHAttributedLabel also allows the usage of html markup to style your label text.

Related

Run TTS in NSArray sequentially

I have NSArray with words in it.
I want to app reads that tts sequentially and print the text in UILabel what app speak.
but word on label is shown the last one.
I tried time pause, etc
for (Word * w in ttswords) {
[self speechword:w];
}
-(void)speechword:(Word*)w{
utterance = [[AVSpeechUtterance alloc] initWithString:[w.title stringByReplacingOccurrencesOfString:#"~" withString:#""]];
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:#"en-US"];
[synthesizer speakUtterance:utterance];
_lb_title.text = w.title;
}
I want to execute one by one.
The best way to highlight the vocalized word is using the speechSynthesizer:willSpeakRangeOfSpeechString:utterance: method of the AVSpeechSynthesizerDelegate protocol.
If you don't use this delegate method, you won't be able to reach your goal.
Take a look at this complete and useful example (ObjC and Swift) that displays each vocalized word in a bold font with the speech synthesis.

How can I justify the text or make it stop separating the words in a UITextview?

I have an application with a chat, which the design is made with code in objective-c, but in the dialogues the words are broken. How can I justify the text or do a kind of word wrap for the UItextview?
This is an image of what I'm talking about
https://serving.photos.photobox.com/5690512502fd6b9b94cda7ff55dae480af40b3eaf5d952204e938af42be59226a480c160.jpg
I added a HypherationFactor of 1 but the problem is not solved, just fix some. I've been trying for a while and I can not do it.
_textView=[[UITextView alloc] init];
[_textView setTextContainerInset:UIEdgeInsetsZero];
_textView.textContainer.lineFragmentPadding = 0;
_textView.dataDetectorTypes=UIDataDetectorTypeAll;
_textView.font=[UIFont systemFontOfSize:17];
_textView.textColor=kTextColor;
_textView.layoutManager.hyphenationFactor = 1;
_textView.backgroundColor=[UIColor clearColor];
_textView.scrollEnabled=NO;
_textView.editable=NO;
I want the words to be understood; for example: tempera-
ture
You Just need to add one line code in your textView code.
textView.textContainer.lineBreakMode = NSLineBreakByWordWrapping;

NSTokenField: different colors for tokens

I have created an NSTokenField in my xib. I'd like to display tokens with different colors inside that tokenField. Meaning: some tokens will be blue, the rest will be red (according to their content). Is that possible?
The following code doesn't work for me. I hope someone can help me out:
- (id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString
{
id returnRepresentedObject = nil;
NSTokenFieldCell *tf = [[NSTokenFieldCell alloc] init];
tf.stringValue = editingString;
tf.backgroundColor = [NSColor redColor];
returnRepresentedObject = tf;
return returnRepresentedObject;
}
Result: all tokens remain blue... :-(
Any help will be highly appreciated!
Its possible by using private APIs. Subclass NSTokenAttachmentCell (Private) and NSTokenFieldCell.
Sample project
Use BWTokenAttachmentCell and BWTokenFieldCell class and NSTokenAttachmentCell class dump from BWToolkit. Modify initialize method of BWTokenAttachmentCell.
[sample project
NOTE:
Use this method if you are not targeting for Mac App Store.
You'll probably have to role your own. There is a wwdc video from 2010 about advanced Cocoa Text handling. The NSTokenField Uses NSTextAttachments to render the tokens.

Setting the background picture position

Is there any Mac App Store compliant way of setting the desktop wallpaper position to "Stretch to Fill Screen"?
This code sample from Apple provides a good overview of the problem and how to properly code for it in Cocoa. The salient code snippet appears to be the following:
- (void)updateScreenOptions:(NSScreen*)screen
{
if (screen)
{
NSDictionary *screenOptions = [[NSWorkspace sharedWorkspace] desktopImageOptionsForScreen:curScreen];
// the value is an NSNumber containing an NSImageScaling (scaling factor)
NSNumber *scalingFactor = [screenOptions objectForKey:NSWorkspaceDesktopImageScalingKey];
[scalingPopup selectItemAtIndex:[scalingFactor integerValue]];
// the value is an NSNumber containing a BOOL (allow clipping)
NSNumber *allowClipping = [screenOptions objectForKey:NSWorkspaceDesktopImageAllowClippingKey];
[[clippingCheckbox cell] setState:[allowClipping boolValue]];
// the value is an NSColor (fill color)
NSColor *fillColorValue = [screenOptions objectForKey:NSWorkspaceDesktopImageFillColorKey];
if (fillColorValue)
[fillColor setColor:fillColorValue];
}
}
As mentioned in some of the answer errata, the correct method calls here to resolve your question appear to be [screenOptions setObject:scalingFactor forKey:NSWorkspaceDesktopImageScalingKey] and [[NSWorkspace sharedWorkspace] setDesktopImageURL:imageURL forScreen:curScreen options:screenOptions error:&error], which should provide the desired functionality.
I freely admit this was a collaborative effort, but it seems we've blundered through to a correct solution.
(Additional information on the NSImageScaling enumeration and NSWorkspace, which contains the correct scaling keys.)
Unfortunately there is no Mac App Store compliant way of setting the desktop image options. They only methods available with regards to desktop images are:
– desktopImageURLForScreen:
– setDesktopImageURL:forScreen:options:error:
– desktopImageOptionsForScreen:
You may be able to do it by executing an AppleScript, though I do not think Apple will like that.
Hope this helps!
EDIT:
[screenOptions setObject:scalingFactor forKey:NSWorkspaceDesktopImageScalingKey];
[[NSWorkspace sharedWorkspace] setDesktopImageURL:imageURL forScreen:curScreen options:screenOptions error:&error];

Cocoa: pasting formatted text in the current font?

When I put formatted text into the pasteboard (NSRTFPboardType), it pastes with all formatting preserved. But what I'd really like is to discard the font face and size information, while preserving the weight, color, etc.
According to the docs, an NSAttributedString with no font information will default to Helvetica 12, so that seems like a dead end.
I can also generate the text on demand, so if I could find out the font in the current UI element, I could modify the text before it goes into the pasteboard. I was hoping the accessibility API could help with this, but none of the attributes I can find in the UIElementInspector seem to deal with formatting.
Any ideas?
Here's a test case. It pastes in Helvetica 12 even though the only attribute is a green color:
// Create the string with no attributes, and strip the font just in case.
NSMutableAttributedString *s = [[[NSMutableAttributedString alloc] initWithString:#"Hello green world!"] autorelease];
[s removeAttribute:NSFontAttributeName range:NSMakeRange(0, [s length])];
// Add a test attribute
[s addAttribute:NSForegroundColorAttributeName value:[NSColor greenColor] range:NSMakeRange(6, 5)];
// Generate RTF data
NSData *rtf = [s RTFFromRange:NSMakeRange(0, [s length]) documentAttributes:nil];
// Copy to pasteboard
NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSRTFPboardType] owner:nil];
[pb setData:rtf forType:NSRTFPboardType];
Here's something interesting. If I try and generate the plainest raw RTF data I can, with absolutely no font information, it still pastes in Helvetica 12!
char *rawrtf = "{\\rtf1\\ansi\\ansicpg1252\n"
"Hello world.}";
NSData *rtf = [NSData dataWithBytes:rawrtf length:strlen(rawrtf)];
So if this is possible at all, I think it's only possible by querying the currently running application about the current font.
There is no system-wide or even application-wide notion of the "current font". The closest you can get is the typing attributes of a currently active NSTextView; if none is active, then there is nothing like a current font.
With that said, you could promise the RTF data to the pasteboard, and when it requests it, send the currently active application a copy AppleEvent command, wait for a response, pull any rich text off the pasteboard, and grab its font attributes. If no rich text is available, stick with your current font and size. I have no idea how well this heuristic works in practice, but I can't think of any better approach.
If I try and generate the plainest raw RTF data I can, with absolutely no font information, it still pastes in Helvetica 12!
The font defaults to Helvetica-12 when no font information is supplied because all text being drawn has to be in some font at some size. Helvetica-12 must have seemed as readable and sufficiently inoffensive to be chosen as the default. (Sure beats Comic Sans-72!)
NSAttributedString is immutable. I think perhaps what you need is an NSMutableAttributedString. This guide has an example of how to change things. You should be able to create a new NSMutableAttributedString as a copy of the NSAttributedString, and then make your modifications to it before passing it on to the pasteboard.
EDIT:
I'm not quite sure of what you what to do. You are saying that you want to preserve some formatting, and remove other formatting, and it seems like you understand how to manipulate the NSMutableAttributedString attributes, so what's the problem? Create a new attributed string, interrogate the old one, and apply whatever attributes you want to the new one, if you don't like the default font, change it. I'm not understanding where the problem is in this.
EDIT2:
Using initWithAttributedString: should copy the font properties over, but if it doesn't you should be able to use enumerateAttributesInRange:options:usingBlock: to interrogate your original NSAttributedString
EDIT3:
NSAttributedString *attrStr;
NSRange limitRange;
NSRange effectiveRange;
id attributeValue;
limitRange = NSMakeRange(0, [attrStr length]);
while (limitRange.length > 0) {
attributeValue = [attrStr attribute:NSFontAttributeName
atIndex:limitRange.location longestEffectiveRange:&effectiveRange
inRange:limitRange];
// apply attributeValue to the other mutable attributed string range here
limitRange = NSMakeRange(NSMaxRange(effectiveRange),
NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
}
changing copied text so it'll be different from what the user had copied would go against the idea of copy and paste, no?