Displaying currency signs in UILabel on Xcode - xcode

I am trying to display the gliphs for a currencies by using either the html format or unicode one. By using the former I tried all sorts of operations including: stringWithUTF8String, decodeFromPercentEscapeString, CFURLCreateStringByReplacingPercentEscapesUsingEncoding, stringByReplacingPercentEscapesUsingEncoding but none of them succeded in turning € into a euro sign. With Unicode the issue was slightly better as:
NSString *aStr = [NSString stringWithUTF8String:[#"\u20ac" UTF8String]];
actually prints a euro sign, but for I reason I do not understand, if I provide the string as the result of a method, the unicode code gets displayed instead.
What is the standard way for displaying euro, dollar or pounds signs in a UILbel?

UILabel automatically resolves unicode strings, no need to decode:
label.text = #"\u0024"; // dollar
label.text = #"\u20ac"; // euro
Refer to fileformat.info for the encoding name.

What about directly copying and pasting those characters in your string as :
NSString *aStr = #"Euro-€, Dollar-$, Pound-£";
label.text=aStr;

I found a very simple solution:
float fareValue=/*float value*/;
NSNumber* fareNumber=[NSNumber numberWithFloat:fareValue];
NSString* formatted=[NSNumberFormatter localizedStringFromNumber:fareNumber numberStyle:NSNumberFormatterCurrencyStyle];
Thanks everyone

Swift 3
"\u{00A3}"
The '#' is no longer needed

Related

Converting a font character number into a string

I'd like to draw a specific character number in a font using NSString's drawAtPoint() routine.
To do this I've been casting the integer value of the specific character into an NSString:
int characterNumber = 150; //character 150 in a particular font
NSString* myString = [NSString stringWithCharacters:(const unichar*)&characterNumber length:1];
This works if the character number is less than 128. If the characterNumber is greater than that (my font contains 200+ characters) then no character prints. If the character number is 150, and I change the string length to 2, then the wrong character from the font prints.
Is this an encoding issue?
Shouldn't that be:
unichar characterNumber = 150; //character 150 in a particular font
NSString* myString = [NSString stringWithCharacters:&characterNumber length:1];
The problem, it turned out, is that character 0x007F (127) is the DEL character, and is unprintable.
Other issues I had with my custom font turned out to be issues of encoding, which had to be worked out in Fontographer, rather than in NSString.

NSMutableParagraphStyle ignores NSWritingDirectionNatural, is defaulting to LTR for arabic text

I'm using the NSAttributedString UIKit Additions to draw an attributed string in a UIView. The problem I have is that despite using a value of NSWritingDirectionNatural for the baseWritingDirection property of my paragraph style, text always defaults to left-to-right.
Here's how I form the attributed string (simplified):
NSString *arabic = #"العاصمة الليبية لتأمينها تنفيذا لقرار المؤتمر الوطني العام. يأتي ذلك بعدما أعلن اللواء الليبي المتقاعد خليفة حفتر أنه طلب من المجلس الأعلى للقض الدولة حتى الانتخابات النيابية القادمة";
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.baseWritingDirection = NSWritingDirectionNatural;
paragraph.lineBreakMode = NSLineBreakByWordWrapping;
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
attributes[NSParagraphStyleAttributeName] = paragraph;
NSAttributedString *string = [[NSAttributedString alloc]
initWithString:arabic
attributes:attributes];
And here's how I draw the text:
- (void)drawRect:(CGRect)rect {
[self.attributedText drawWithRect:rect
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
}
And yet it still flows from left to right:
What am I missing?
I don't believe the writing direction will be automatically set for you using baseWritingDirection unless you switch languages on the device:
"If you specify NSWritingDirectionNaturalDirection, the receiver resolves the writing direction to either NSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft, depending on the direction for the user’s language preference setting."
For some reason the text you have still doesn't seem to work even with arabic selected without adding the language to your supported localizations. This character seemed to work without doing that for me: كتب
Also, it looks like Xcode reverses the characters in hardcoded arabic strings so that may be screwing with some of this copy and paste.
You can use agiletortoises's suggestion or NSLinguisticTagger's Language tag scheme to manually set the language.
I can't explain why it does not work the way you have it written, but I've been using a solution to explicitly set the direction based on known RTL languages, which used this as a starting point:
https://stackoverflow.com/a/16309559
No idea if this is related or not, but when I tested the right-to-left support in Auto Layout, it didn't work until I added a localization for that language (Arabic, Hebrew, etc) to the app.

How to change an NSString's encoding?

I have an NSArray of NStrings, I got this from NSLog when printing the array.
Here is the code I have implemented:
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
.....
NSArray *queryResults = [[query results] copy];
for (NSMetadataItem *item in queryResults)
{
id value = [item valueForAttribute: kMDItemAlbum];
[databaseArray addObject: value];
}
"The Chronicles Of Narnia: Prince Caspian",
"Taste the First Love",
"Once (Original Soundtrack)",
"430 West Presents Detroit Calling",
"O\U0308\U00d0\U00b9u\U0301\U00b0\U00aeA\U0300O\U0308A\U0300O\U0308I\U0301A\U030a-O\U0301a\U0300A\U0302\U00a1",
"\U7ea2\U96e8\U6d41\U884c\U7f51",
"I\U0300\U00ab\U00bc\U00abO\U0303A\U030aE\U0300y\U0301\U00b7a\U0301",
"A\U0303n\U0303\U00b8e\U0300\U00b2I\U0300C\U0327U\U0300",
"\U00bb\U00b3A\U0308i\U0302O\U0303\U00bdO\U0301N\U0303",
"American IV (The Man Comes Aro",
"All That We Needed",
Now how can I change the human-unreadable strings to human-readable strings? Thanks.
Looking past the escaping done by description (e.g., \U0308), the strings are wrong (e.g., “Öйú°®ÀÖÀÖÍÅ-Óà¡”) because the data you got was wrong.
That's probably not Spotlight's fault. (You could verify that by trying a different ID3-tag library.) Most probably, the files themselves contain poorly-encoded tags.
To fix this:
Encode it in the 8-bit encoding that matches the characters. You can't just pick an encoding (like “ASCII”, which Cocoa mapped to ISO Latin 1 the last time I checked) at random; you need to use the encoding that contains all of the characters in the input and encodes them correctly for what you're going to do next. Try ISO Latin 1, ISO Latin 9, Windows codepage 1252, and MacRoman, in that order.
Decode the encoded data as UTF-8. If this fails, go back to step 1 and try a different encoding.
If step 2 succeeds on any attempt, that is your valid data (unless you're very unlucky). If it fails on all attempts, the data is unrecoverable and you may want to warn the user that their input files contain bogus tags.
Parsing these kind of strings aren't particularly easy: See this SO post for background. It's got links to other SO posts with specific ways of handling this problem.
These strings are utf-8 encoded. You can decode them by:
NSString *myDecoded = [NSString stringWithUTF8String:myEscapedString];
So to process your complete array 'completeArray' you can convert to a const char* first and then back into NSString:
NSMutableArray *processed = [NSMutableArray arrayWithCapacity:completeArray.count];
for (NSString* s in completeArray) {
[processed addObject:[NSString stringWithUTF8String:[s cStringUsingEncoding:ASCIIEncoding]]];
}

NSString's isEqualToString: seems to erroneously report non-equality

I'm trying to compare the equality of two multi-line strings. I'm getting one of the strings from a web service, and the other I'm getting from iTunes via the Scripting Bridge. The strings from the web service are eventually transferred to iTunes, so if I do that and then re-compare the strings, ideally they'd be identical.
However, when comparing strings like this, it seems that isEqualToString: always returns non-equality. I'm testing this by testing equality of a string from iTunes that originally came from the web service, and a string directly from the web service.
Logging both strings to the Console produces output from both strings that appears identical. Logging the lengths of the strings produce identical lengths.
I've also tried comparing the strings using some other methods. For example, I converted them to ASCII strings to make sure it wasn't some Unicode issue:
NSData *iTunesStringData = [[self iTunesString] dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
NSData *webServiceStringData = [[self webServiceString] dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
NSString *newiTunesString = [[[NSString alloc] initWithData:iTunesStringData encoding:NSASCIIStringEncoding] autorelease];
NSString *newWebServiceString = [[[NSString alloc] initWithData:webServiceStringData encoding:NSASCIIStringEncoding] autorelease];
BOOL result = [newiTunesString isEqualToString:newWebServiceString];
Same problem, not equal. I've tried comparing just the first character:
NSComparisonResult result = [newiTunesString compare:newWebServiceString
options:NSLiteralSearch
range:NSMakeRange(0,1)
locale:[NSLocale currentLocale]];
Does not return NSOrderedSame. I've logged these first characters to the Console and they seem identical. I also considered differences in carriage returns, and tried replacing #"\r" with #"" in both strings before comparing, which doesn't work (and besides, that shouldn't affect equality of just the first character). I don't want to remove #"\n" characters because I want to preserve the multiple lines.
What's going on? Any other ideas?
It turns out this problem was related to line endings. But since I'm comparing multi-line strings, I didn't want to completely strip out the newlines. I normalized the line endings like so:
NSString *normalizediTunesString = [[[self iTunesString] componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:#"\n"];
NSString *normalizedWebServiceString = [[[self webServiceString] componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:#"\n"];
Then, comparing the strings via compare: worked as expected.
Just guessing here but maybe use this clean up your strings
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]

Easy way to set a single character of an NSString to uppercase

I would like to change the first character of an NSString to uppercase. Unfortunately, - (NSString *)capitalizedString converts the first letter of every word to uppercase. Is there an easy way to convert just a single character to uppercase?
I'm currently using:
NSRange firstCharRange = NSMakeRange(0,1);
NSString* firstCharacter = [dateString substringWithRange:firstCharRange];
NSString* uppercaseFirstChar = [firstCharacter originalString];
NSMutableString* capitalisedSentence = [originalString mutableCopy];
[capitalisedSentence replaceCharactersInRange:firstCharRange withString:uppercaseFirstChar];
Which seems a little convoluted but at least makes no assumptions about the encoding of the underlying unicode string.
Very similar approach to what you have but a little more condense:
NSString *capitalisedSentence =
[dateString stringByReplacingCharactersInRange:NSMakeRange(0,1)
withString:[[dateString substringToIndex:1] capitalizedString]];
Since NSString is immutable, what you have seems to be a good way to do what you want to do. The implementations of (NSString*)uppercaseString and similar methods probably look very much like what you've written, as they return a new NSString instead of modifying the one you sent the message to.
I had a similar requirement, but it was for characters within the string. This assuming i is your index to the character you want to uppercase this worked for me:
curword = [curword stringByReplacingCharactersInRange:NSMakeRange(i,1)
withString:[[curword substringWithRange:NSMakeRange(i, 1)] capitalizedString]];
If you profile these solutions they are much slower then doing this:
NSMutableString *capitolziedString = [NSMutableString stringWithString:originalString];
NSString *firstChar = [[capitolziedString substringWithRange:NSMakeRange(0,1)] uppercaseString];
[capitolziedString replaceCharactersInRange:NSMakeRange(0, 1) withString:firstChar];
in testing on an iphone 4 running iOS 5:
#doomspork's solution ran in 0.115750 ms
while above ran in 0.064250 ms;
in testing on an Simulator running iOS 5:
#doomspork's solution ran in 0.021232 ms
while above ran in 0.007495 ms;
Aiming for maximum readability, make a category on NSString and give it this function:
NSString *capitalizeFirstLetter(NSString *string) {
NSString *firstCapital = [string substringToIndex:1].capitalizedString;
return [string stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:firstCapital];
}
Then in your code where you want it:
NSString *capitalizedSentence = capitalizeFirstLetter(dateString);
This kind of code rarely belongs in the spot where you need it and should generally be factored away into a utility class or a category to improve legibility.

Resources