NSURL withString adds gibberish - ios

I am trying to build a NSURL using a path string. The string looks fine but when I try to put that in an NSURL it gets a bunch of gibberish in it. Here is the code I am using to build up the url:
NSString* path = [[AppSettings instance].contentRootPath stringByAppendingPathComponent: item.fileName];
NSLog(path);
item.contentPath = [NSURL URLWithString:[path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(item.contentPath.absoluteString);
And here is the log:
2012-07-25 10:28:39.983 mxHub[44036:207] /Users/casey.borders/Library/Application Support/iPhone Simulator/5.0/Applications/C2C1975D-7FAB-4E6C-A091-DC389223CC57/Documents/.content/PREZISTA-PI.pdf
2012-07-25 10:28:41.654 mxHub[44036:207] /Users/casey.borders/Library/Application扡潳畬整瑓楲杮䄀䅖獳瑥慃档e獡敳䍴捡敨楗桴剕㩌猀穩佥䕦瑮祲潆䭲祥:ㅱ䀲㨰䀴8敲潭敶湅牴䙹牯敋㩹挀牵敲瑮楓敺猀瑥慍䕸瑮祲楓敺:慭䕸瑮祲楓敺猀瑥慍卸穩㩥洀硡楓敺䀀䄢䅖獳瑥慃档䥥瑮牥慮≬䄀䅖獳瑥慃档䥥瑮牥慮l湩瑩楗桴楄瑣潩慮祲:慤慴獕湩䕧据摯湩㩧污潬䱷獯祳潃癮牥楳湯:慣䉮䍥湯敶瑲摥潔湅潣楤杮:湩瑩楗桴慄慴攺据摯湩㩧攀瑸湥敤䱤杯慄慴瑓楲杮湅潣楤杮攀瑸湥敤䱤杯慄慴䄀偖慬敹䥲整䅭捣獥䱳杯开捡散獳潌䅧牲祡攀敶瑮s灟慬敹䥲整䅭捣獥䱳杯䀀䄢偖慬敹䥲整䅭捣獥䱳杯湉整湲污"噁汐祡牥瑉浥捁散獳潌䥧瑮牥慮l潬䅧牲祡䄀偖慬敹䥲整䅭捣獥䱳杯癅湥t畮扭牥晏牄灯数噤摩潥牆浡獥椀摮捩瑡摥楂牴瑡e扯敳癲摥楂牴瑡e畮扭牥晏祂整味慲獮敦牲摥渀浵敢佲卦慴汬s畤慲楴湯慗捴敨d敳浧湥獴潄湷潬摡摥畄慲楴湯瀀慬批捡卫慴瑲晏獦瑥瀀慬批捡卫獥楳湯䑉渀浵敢佲卦牥敶䅲摤敲獳桃湡敧s敳癲牥摁牤獥s剕I汰祡慢正瑓牡䑴瑡e畮扭牥晏敓浧湥獴潄湷潬摡摥开汰祡牥瑉浥捁散獳潌䕧敶瑮䀀䄢偖慬敹䥲整䅭捣獥䱳杯癅湥䥴瑮牥慮≬吀ⱤⱒN噁汐祡牥瑉浥捁散獳潌䕧敶瑮湉整湲污搀捩t┊#噁汐祡牥瑉浥牅潲䱲杯开牥潲䱲杯牁慲y灟慬敹䥲整䕭牲牯潌g≀噁汐祡牥瑉浥牅潲䱲杯湉整湲污"噁汐祡牥瑉浥牅潲䱲杯湉整湲污䄀偖慬敹䥲整䕭牲牯潌䕧敶瑮攀牲牯潃浭湥t牥潲䑲浯楡n牥潲卲慴畴䍳摯e灟慬敹䥲整䕭牲牯潌䕧敶瑮䀀䄢偖慬敹䥲整䕭牲牯潌䕧敶瑮湉整湲污"噁汐祡牥瑉浥牅潲䱲杯癅湥䥴瑮牥慮l椀剳捥牯楤杮攀牲牯楗桴潄慭湩挺摯㩥獵牥湉潦:潶捩䍥湯牴汯敬䕲摮汐祡慢正湉整牲灵楴湯:潶捩䍥湯牴汯敬䕲摮敒潣摲湉整牲灵楴湯:潶捩䍥湯牴汯敬偲慬批捡䉫晵敦䅲慶汩扡敬戺晵敦㩲瘀楯散潃瑮潲汬牥楄卤慴瑲汐祡湩㩧畳捣獥晳汵祬:upport/iPhone ㈜ǪᶀЀꀠ/Āࠀ쵠޴imulator/5.0/Applications/C2C1975D-7FAB-4E6C-A091-DC389223CC57/Documents/.content/Demo.pdf

It's to do with NSLog, nothing to do with your urls :)
Try this :
NSString* path = [[AppSettings instance].contentRootPath stringByAppendingPathComponent: item.fileName];
NSLog(#"%#", path);
item.contentPath = [NSURL URLWithString:[path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"%#", item.contentPath.absoluteString);
The first parameter for NSLog is a format string - this tells NSLog that there might be other values to insert into the output (these are the other optional parameters that NSLog takes - for example NSLog(#"%i", 5); would replace the %i with 5).
The NSLog(path); is fine because there aren't any special formatting characters in the path so it outputs as you would expect.
The second NSLog has % characters in - you added them when you asked to % escape the path :) For example, you replaced the space in 'Application Support' with %20.
This means that your url now contains the formatting code %20S (the S is the next character after the space, the first character in the word 'Support').
%S is interpreted by NSLog as 'take the next paramter that I have been given and treat it as a null terminated c-string'.
Unfortunately, you didn't give NSLog another parameter :) However, NSLog didn't know that - it just dutifully did as it was told and took the next value on the stack and added it to the output string.
The next value on the stack is garbage which is why your output is garbage!
You can see that the corrupted values appear instead of the spaces in your path - both spaces happen to be followed by an S so NSLog is dumping garbage in two places. That's why after the first load of garbage you can see 'upport/iPhone' and after the second 'imulator/5.0' :)

When you use NSLog(string), that string is treated as a format statement and any '%' characters will be interpreted.
Try printing the strings out using this form: NSLog(#"%#", string). As a general statement you should ALWAY use the above form and never the one you are using.

Related

Unity / Objective-C: Trouble converting char* to NSString

I have what should be a dead-simple piece of code that is failing for me in strange ways.
void MediaShare(char* text, char* furl) {
NSString *status = [NSString stringWithUTF8String: text];
NSString *media = [NSString stringWithUTF8String: furl];
[[SocialShare sharedInstance] mediaShare:status media:media];
text is just a line of text for Twitter sharing, and furl is just a file location string. I am getting a crash down past this function that comes down to bad data getting passed. Putting a breakpoint at the head of this function yields the following-
Image of Xcode variable monitor
The two values look fine, although not sure if the * values that only contain the first char are a problem.
Anyway, jumping to the end, and status and media appear to be converted to hex values.
Converted to hex values?
Any ideas? To give the full story, this is a Unity plug-in. I am simply passing in two strings from Unity C# to this function.
Thanks so much.
The code looks fine so far, if the input values are well formed C char* strings that can be interpreted as an UTF-8 encoded string.
status and media being hex values at the end of the function hint that they are. Both are pointers to Objective-C objects, so this is expected. Print them to the debug console or use po status at the debug console to check their contents (it will print the result of the -description method of status which is the string content in that case).
The subsequent crash might be caused elsewhere in the code.
What's the crash's log output?

NSURl urlWithString replaces body with dots

I try to convert NSString to NSURL however I receive truncated url.
NSURL *url = [NSURL fileURLWithPath:music.url];
If I make NSLog music.url I get:
/Users/Nikita/Library/Developer/CoreSimulator/Devices/D93FE148-7F72-43BB-A545-06D76C71300B/data/Containers/Data/Application/48BC6629-F054-4679-AC7B-709815EC5E2A/Library/Caches/4219609-357670045.mp3
And when NSLog received url:
/Users/Nikita/Library/Developer/CoreSimulator/Devices/D93FE148-7F72-43BB-A545-06D76C71300B/data/Containers/Data/Applicat ... 0045.mp3
The link is partially truncated.
What is the reason?
Thank you
music.ulr is obviously an instance of NSString. url is an instance of NSURL. Using NSLog() an instance of a class makes its own decision how to be logged.
Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function.
NSLog() prints only a description, not the complete object, whatever this should be.
Obviously the developer of NSString thought, that it is a good idea to print out the complete string and wrote a description method doing that. The developer of NSURLthought that it is enough to print the string partially, so you can recognize it.

cant get 100,000+ hebrew characters into objective-c string

I have 100,000+ characters of text that need to be converted into a string so I can count the characters and display them on a page correctly, but in the text there are tons of quotations ("") and lots of commas, so it doesnt even turn into a string.
Does anyone know a way that you can ignore quotations and commas inside a NSString without having to do this \"" each time?
Here's some of the text. its english/hebrew
Psalm 30
...
Psalm 100
...
The following Psalm is not to be said on Shabbat, Festivals, the day before Pesach, Chol HaMoed Pesach, and the day of Yom Kippur
...
You say “I cant even turn the text into a string”. Since you said (in a comment) you're “just pulling it off this website”, the simplest way to do this is +[NSString stringWithContentsOfURL:encoding:error:]. This works for me:
NSURL *url = [NSURL URLWithString:#"http://opensiddur.org/wp-content/uploads/2010/08/The-Blessing-Book-Nusa%E1%B8%A5-Ha-Ari-%E1%B8%A4aBaD-3.2.txt"];
NSError *error;
NSString *text = [NSString stringWithContentsOfURL:url usedEncoding:nil error:&error];
NSLog(#"error=%# text.length=%lu", error, (unsigned long)text.length);
You can look into NSURLSession or NSURLConnection when you want to do it in a non-blocking fashion.
If you plan to distribute the text in a file (named, let's say, “blessingBook.txt”) in your app bundle, you can get the URL this way:
NSURL *url = [[NSBundle mainBundle] URLForResource:#"blessingBook" withExtension:#"txt"];
If you're loading it directly from your app bundle, you probably don't need to worry about using NSURLSession to load it in the background. You might want to do your “processing” in the background though, if it takes a while.
You can replace the punctuation or commas or what ever you want to #"" (empty string).
yourString=[yourString stringByReplacingOccurrencesOfString:#"," withString:#""];
yourString=[yourString stringByReplacingOccurrencesOfString:#":" withString:#""];
yourString=[yourString stringByReplacingOccurrencesOfString:#";" withString:#""];
What ever the text you want to replace. Replace as above.
But it is lengthy process finding un wanted quotations, commas..some characters and replace with empty string..
Hope it helps you..!

iOS Conversion from a dictionary to a NSString

I have a NSMutableDictionary holding EXIF metadata from a picture.
An example:
const CFStringRef kCGImagePropertyExifExposureTime;
Instead of accessing every key individually, I just want write the whole dictionary content into a label.
When I want to write this data into the console I would just use:
NSLog(#"EXIF Dic Properties: %#",EXIFDictionary );
That works fine, but if I use:
NSString *EXIFString = [NSString stringWithFormat:(#"EXIF Properties: %#", EXIFDictionary)];
I get warnings that the result is not a string literally and if I try to use that string to set my label.text, the program crashes.
Any idea where my error is?
[NSString stringWithFormat:(#"EXIF Properties: %#", EXIFDictionary)] is not, as you may think, a method with two arguments. It's a method with one argument. That one argument is (#"EXIF Properties: %#", EXIFDictionary), which uses the comma operator and ends up returning EXIFDictionary. So in essence you have
[NSString stringWithFormat:EXIFDictionary]
which is obviously wrong. This is also why you're getting a warning. That warning tells you that the format argument is not a string literal, because using variables as format strings is a common source of bugs. But more importantly here, that argument isn't even a string at all, and so it crashes.
Remove the parentheses and everything will be fine. That will look like
[NSString stringWithFormat:#"EXIF Properties: %#", EXIFDictionary];
I get warnings that the result is not a string literally
Nah. You get a warning saying that the format string of stringWithFormat: is not a string literal. That's because you don't know how the comma operator (and a variadic function) works (that's why one should master the C language before trying to make an iOS app). Basically what you have here:
[NSString stringWithFormat:(#"EXIF Properties: %#", EXIFDictionary)]
is, due the behavior of the comma operator, is equivalent to
[NSString stringWithFormat:EXIFDictionary]
which is obviously wrong. Omit the parentheses, and it will be fine:
[NSString stringWithFormat:#"EXIF Properties: %#", EXIFDictionary]
You don't want those parentheses:
NSString *EXIFString = [NSString stringWithFormat:#"EXIF Properties: %#", EXIFDictionary];

NSURL not returning nil for one-character non-ascii strings

I have been using NSURL to do a simple URL validation, mostly to weed out non-ascii special characters, which I do not want in my particular application. I take a URL as input into an NSString, then try to create an NSURL using URLWithString. If this returns nil, the app presents an error message.
For example if I enter "あか" as input (that is two Japanese characters), then the NSURL is nil. This has been working as expected. However I recently noticed that entering a string that is contains only one single non-ASCII character, NSURL processes it and returns a URL-encoded value. So if I enter "あ" as input, the resulting NSURL is NOT nil. The absoluteString value is "%E3%81%82".
I'm wondering if this is a bug in NSURL, or some kind of loophole that I'm not understanding.
I'm using Xcode 3.2.5, and the iOS 4.2 SDK.
I can't explain the behavior you are seeing above, however, if all you are trying to do is determine whether a URL string contains any non-ASCII characters, you could achieve this with the following code:
NSString *testURLString = #"http://www.googleあか.com";
NSCharacterSet* ascii = [NSCharacterSet characterSetWithRange: NSMakeRange(0, 128)];
NSCharacterSet* nonAscii = [ascii invertedSet];
if ([testURLString rangeOfCharacterFromSet:nonAscii].location != NSNotFound) {
NSLog(#"This string contains non-ASCII characters");
}

Resources