How to word wrap text in annotation subtitle - iphone

I tried to insert return and newline chars into the subtitle string, but they ended up as "spaces" and not line breaks. Since subtitle is simply an NSString I must look at the container, which likely means I'll have to roll my own annotation views.
The NSString do become f.ex. "90510\nHollywood, CA", but maybe I have to 'encode' the newlines instead, or use a subclass of NSString to send to subtitle?
What baffles me is that surely, subtitle should be able to "be wrappable", as the MKAnnotation(view) handles too long text by resizing the bubble and adding "...", et cetera.
I do need proper word wrap (and not hard line breaks) for a paragraph of text I'm adding later, but I could possibly do that as a separate alert or modal box type, if you know which ones support word wrap I'd be grateful if you could suggest them.
A hunch is that something could be possible by adding a UILabel as a subview, or somehow access the UILabel(?) that is used to display the subtitle, and set its numberOfLines to 0, but I don't know how to do the latter.

AFAIK it can't be done. Setting left/right button text is space-limited indeed. Seems the only solution is to addObserver and roll your own animated views entirely.

Related

NSString UITextView without replacing previous text

How would I go about adding text to a UITextView without replacing the previous text?
So far I have a UITextView and a UIButton that adds the text to the UITextView, but I would like the text field to append more text every time you hit the button instead of completely deleting the text and replacing it.
Here are some ways to overcome obstacles in iOS development:
Look at the documentation for the particular class you're trying to manipulate. In this case, UITextView documentation can be found within Xcode or online.
Command-Click on UITextView or any other object anywhere in your code, and it will bring you to the header file for that class. The header file will list every public method and property.
Look at your existing code. I'm assuming that since you have a button that adds text to a UITextView, you understand how to set its text. 99% of the time you'll find that any setter (mutator) methods will have a corresponding getter (accessor) method. In this case, UITextView has a method called setText: and a matching method just called text.
Finally, NSString has a convenience method called stringWithFormat: that you can use to concatenate (join) two strings, among other very useful things. %# is the format specifier for a string. For example, to combine two strings, stringOne and stringTwo, you could do the following:
NSString *string = [NSString stringWithFormat:#"%# %#", stringOne, stringTwo];
I will leave you to come up with the answer as to how to combine NSString stringWithFormat: and UITextField text and setText: to achieve what you'd like to accomplish.
Edit:
The OP was unable to figure out how to utilize the information above so a complete code sample has been provided below.
Assume you have synthesized property (possibly an IBOutlet) UITextView that you have initialized called myTextView. Assume also that we are currently in the method scope of the method that gets called (your IBAction, if you're using IB) when you tap your UIButton.
[myTextView setText:[NSString stringWithFormat:#"%# %#", myTextView.text, #"this is some new text"]];
Explanation: myTextView.text grabs the existing text inside of the UITextView and then you simply append whatever string you want to it. So if the text view is originally populated with the text "Hello world" and you clicked the button three times, you would end up with the following progression:
Initial String: #"Hello world"
Tap one: #"Hello world this is some new text"
Tap Two: #"Hello world this is some new text this is some new text"
Tap Three: #"Hello world this is some new text this is some new text text this is some new text"
If all you are doing is appending text, you might find this a little simpler:
myTextView.text = [myTextView stringByAppendingString:#"suffix\n"];
I found this on UITextView insert text in the textview text. Sadly, I have not found a way to append text directly without a wholesale replacement of the text in the UITextView. It bugs me that the effort involved is proportional to the total length of the existing string and the suffix, rather than just the suffix.
A more efficient way to append text is to use replace() at the end:
extension UITextInput {
func append(_ string : String) {
let endOfDocument = self.endOfDocument
if let atEnd = self.textRange(from: endOfDocument, to: endOfDocument) {
self.replace(atEnd, withText: string)
}
}
}
#Jack Lawrence: Your answer doesn't cover the question completely.
The example below will not scroll neatly while running off the bottom when called every second:
self.consoleView.text = [NSString stringWithFormat:#"%#%#%#", self.consoleView.text, data, #"\n"];
[self.consoleView scrollRangeToVisible:NSMakeRange(self.consoleView.text.length, 0)];
This is caused by setText replacing the original text every time thereby resetting associated contentOffsets etc.
This was possible prior to iOS 7, but since iOS 7 it seems that setText cannot be prevented from exhibiting jumpy behaviour. Appending does not seem to be an option for TextViews in this scenario?

Overriding Emoji Graphics

I want to override the emoji icons with my own custom graphics (only within my app).
From what I've read so far, one possible solution is to create a custom font extension which overrides the desired unicode characters. Preferable I would like to maintain inter-operability with CATextLayer.
Edit: Looks like custom fonts won't be my solution; fonts must be defined in gray-scale. Next possibility: Creating a custom CALayer, chunking the string into segments based on emoji code, and doing the type setting + graphics rendering manually (i.e. with core graphics and core text)
Edit: Also looking to maintain smooth scrolling performance in a table views.
I have devoted a lot of time trying to do the same. Your best bet is to replace the unicode values for the emoji in your NSString eg. \uE100 etc. with a placeholder string. You could replace the emoji encodings with an HTML Tag and use either UIWenViews or DTCoreText to draw the image inline.
I have done this, it works too, but it will be a little slow (Specially if you want to display this Label in table views.)
Here is a little starter:
Make a dictionary with UIImages as objects and placeholder strings as keys:
self.emoticonDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"happyEmoticon.png", #":)",
#"sadEmoticon.png", #":(",
#"testImg.png", #"\uE100",
nil];
__block NSString *text1 = [NSString stringWithFormat:#"<html><p>%#</p></html>",text];
[self.emoticonDict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
text1 = [text1 stringByReplacingOccurrencesOfString:key withString:[NSString stringWithFormat:#"<img height= 15 width= 15 src=\"%#\">",obj]];
}];
You can at this point load this HTML into a UIWebView and you will have what you want.
[myWebView loadData:_htmlData MIMEType:#"text/html" textEncodingName:#"utf-8" baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];//do create the webview first
If the slow speed of a UIWebView is a concern, you can read ahead. In either case do look at the note towards the end of this answer.
To create a DTAttributedLabel, we do the following:
First we build a NSattributedString using the DTHTMLAttributedStringBuilder:
NSAttributedString *temp = [[[DTHTMLAttributedStringBuilder alloc] initWithHTML:text1
options:#{
DTDefaultFontFamily: #"Helvetica",
DTDefaultFontSize:#15,};
documentAttributes:nil]
generatedAttributedString];
Then you can use a DTAttributedLabel instance to display temp.
self.tempLabel.attributedString = temp;//create a DTAttributedLabel Instance called tempLabel before this, I had it as a property
My objective was to generate text label's really fast (Table Views) while supporting custom emoticons. DTAttributedLabels are fast (much faster than a UIWebView)
NOTE:
I also made a custom font where I had mapped the unicode values for the emojis to a custom glyph. To my surprise, still the default emojis were displayed. I would like to claim here that whenever iOS (CoreText) comes across a character whose value lies in the Emoji section, it draws it using the AppleColorEmoji font by default. The lack of documentation on how Apple Color Emoji font is actually drawn on iOS actually makes it difficult for me to prove this, but this seems to be a plausible explanation.
If you drop an emoji from the character palette app onto a file in textEdit, then select it and try to change the font, you see that it doesn't happen.
Similarly, if you type some text, then select it and try to change it's font to Apple Color Emoji, you'll see it doesn't happen. When I decompiled the Apple Color Emoji font, I didn't find character mappings or glyphs for textual characters (except 0-9). Somehow, even if you set a label's font as Apple Color Emoji, the font for the textual (non-emoji) part of your label's text is set to something else.
Kindly feel free to comment and share your knowledge since this region around the Apple Color Emoji font still remains very unclear.
One solution would be to use the UITextField or TextView delegate and listen to the user's input. When they type an emoji character, pop in a UIImageView inline with the text, and delete the emoji icon with the input.
There's a few mentions of this issue on Apple's private devforums (which you have access to if you're a registered member of the iOS developer program).
It sounds like the potential solution would be to explicitly set the font for whatever you're trying to display.

Entering text-data into a Table cell, without having a UITextField in each cell

I would like to let the user fill in some data to be submitted.
So I have a table with 7 cells, each of them are labeled so they know what data goes into the field.
I though about putting a UITextField in each cell, but it looks like its out of place and the user can enter up to 255 chars, so also it doesn't display the data so nicely.
Can anybody recommend a good way to handle this kind of thing, whats the best solution in your experience?
Maybe hiding the UITextField after they are done entering data and display the data in some other manner?
Kind Regards,
-Code
You can customize a UITextField in several different ways to make it not look out of place to you: things such as location, size, alignment, font, font size, background color, and etc. You can have the text field appearance change depending on whether the text field is in the selected table row or not.
You can also have a UITextField delegate pre-check any changes to the text field, and prohibit entering a text length greater than some number of characters, or illegal/unwanted characters, etc.

do I need separate UILabel in a custom UIView to have separate UILabel lines in a UITableViewCell?

do I need separate UILabel in a custom UIView to have separate UILabel lines in a UITableViewCell?
That is, if I want to have a TableViewCell that has all text, but the text needs to contain 4 separate rows for 4 separate strings (e.g. Name, Title, Description, Location), and each these separate rows could include a wrap around.
To ask the question the other way around, is there way with a normal UITableViewCell using it content view and single text label, to force Carriage Return/New Line points at the end of each of the four strings? Oh yes, and the cell height will need to be calculated for each Cell as it may vary (just in case this is significant)
The answer to the last question: NO. (Answer to the title: YES.)
You can build a cell in its own NIB file. An exercise I suggest if you've never done it.
Layout the size/location/resize functionality as you like it.
your table view controller can be the owner of the file,
add an outlet to the TV controller of loadedCell, and call load nib
every time you want to alloc a new cell,
i suggest tagging each of the cell labels, and accessing them
that way, and setting the loadedCell value to nil after loading it,
p.s. a UILabel often wraps text undesirably, or is hard to layout in a cell to look good, consider the other values of lineBreakMode for your labels
p.p.s. it will employ a text shortening behavior depending on adjustsFontSizeToFitWidth and minimumFontSize (taking this and lineBreakMode into consideration)

One label, two different fonts?

I need to format text in a label like this:
username: some text from this user. This will
create additional lines of text that will go
on and on and on.
Where "username" is bold. This will go into a UILabel, which is in a custom table cell. Is there a way to get this type of layout?
For this relatively simple case, you might be able to fake it. Have one label with the bold username, and another label with the plain text in the same position. Insert enough spaces before the plain text to leave room for the username. You can use UIStringDrawing methods to measure the bold text and the spaces.
CGSize usernameSize = [theUsername sizeWithFont:theBoldUsernameFont];
CGSize spaceSize = [#" " sizeWithFont:thePlainCommentFont];
NSString *indentedComment = [NSString stringWithFormat:#"%*s%#" , (int)ceil( usernameSize.width / spaceSize.width ) , "" , theComment];
If you use plain UILabel it's not available. Use two labels for this task.
You need to use either a UIWebView or CoreText to do this kind of advanced text layout. A web view has a lot of overhead but is most flexible and you can't use it effectively in a UITableView cell. CoreText is low level and not that well documented. You could ditch the table view and just lay out the table with CSS and HTML in the web view, which is how I do it.
You can still use a UITableViewCell but have the cell use a UIWebView subview. Set up a custom cell subclass with a clever setter method that allows you to send nsstrings to the method with turns those into a pretty formatted view.