UIPasteboard: NSString refuses to copy to clipboard - ios

I have the following code to shorten a URL using the bit.ly API.
NSString *shortenedURL = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://api.bit.ly/v3/shorten?login=%#&apikey=%#&longUrl=%#&format=txt", login, key, self.link.text]] encoding:NSUTF8StringEncoding error:nil];
I also have the following code to copy the shortened URL to the pasteboard:
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = shortenedURL;
However, this does not work. In the output log, this is what is displayed:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPasteboard setString:]: Argument is not an object of type NSString [(null)]'
So if the argument isn't an object, what is it? I tried assuming it was a URL with this:
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.URL = shortenedURL;
The same type of error is produced, only saying that the argument is not an NSURL object, instead of the previous error saying the argument is not an NSString object.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPasteboard setURL:]: Argument is not an object of type NSURL [(null)]'
Anyone know what to do?

Unfortunately the string property on the UIPasteboard object is not actually a direct reference to a string, but an interface with getters and setters for an Objective-C array of the given type you care about.
Swift provides optionals, but unfortunately UIPasteboard is Objective-C under the hood, which doesn't really support optionals well. This is one of those cases.
If you assign nil (null) to the string property, execution will wrap your null in square brackets as an array [(null)] then attempt to add it to empty array of type [NSURL] and because [(null)] does not match the type of [NSURL] you will get:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPasteboard setURL:]: Argument is not an object of type NSURL [(null)]'
😤
UIPasteboard GitHub doc
unsafe initializer used

NSString *shortenedURL = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://api.bit.ly/v3/shorten?login=%#&apikey=%#&longUrl=%#&format=txt", login, key, self.link.text]] encoding:NSUTF8StringEncoding error:nil];
is nil, so it's not a good idea to ignore the error.
Instead of that, do
NSError *loadingError = nil
NSString *shortenedURL = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://api.bit.ly/v3/shorten?login=%#&apikey=%#&longUrl=%#&format=txt", login, key, self.link.text]] encoding:NSUTF8StringEncoding error:&loadingError];
if (!shortenURL) {
NSLog(#"Error loading: %#", loadingError);
return;
} else {
NSLog(#"Success loading: %#", shortenedURL);
}
You should get "Error loading: error message here", and debug the exact problem what happened.

Related

'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil (key: device_uid)'

I have an error when trying to run the application on my iPhone. I don't understand why I have a nil error in this case
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' setObjectForKey: object cannot be nil (key: device_id)'
First throw call stack: (0x183ce0f48 0x19918bf80 0x183bcc4e0 0x10006f5f0 0x1002b9ca8 0x1002b9c68 0x1002bf710 0x183c981f8 0x183c96060 0x183bc4ca0 0x18f148088 0x1892dcffc 0x1000716a0 0x1999ce8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
Here is the part of appdelegate.m file concerned by this error :
// Get the users Device Model, Display Name, Token & Version Number
UIDevice *device = [UIDevice currentDevice];
NSUserDefaults *dict = [NSUserDefaults standardUserDefaults];
NSString *identifier = [dict stringForKey:#"identifier"];
NSString *deviceName = device.name;
NSString *deviceModel = device.model;
NSString *deviceSystemVersion = device.systemVersion;
// Prepare the Device Token for Registration (remove spaces and < >)
NSString *deviceToken = [[[[token description]
stringByReplacingOccurrencesOfString:#"<"withString:#""]
stringByReplacingOccurrencesOfString:#">" withString:#""]
stringByReplacingOccurrencesOfString: #" " withString: #""];
NSMutableDictionary *postDatas = [NSMutableDictionary dictionary];
[postDatas setObject:appName forKey:#"app_name"];
[postDatas setObject:appVersion forKey:#"app_version"];
[postDatas setObject:identifier forKey:#"device_uid"];
[postDatas setObject:deviceToken forKey:#"device_token"];
[postDatas setObject:deviceName forKey:#"device_name"];
[postDatas setObject:deviceModel forKey:#"device_model"];
[postDatas setObject:deviceSystemVersion forKey:#"device_version"];
[postDatas setObject:pushBadge forKey:#"push_badge"];
[postDatas setObject:pushAlert forKey:#"push_alert"];
[postDatas setObject:pushSound forKey:#"push_sound"];
Request *request = [Request alloc];
request.delegate = self;
[request postDatas:postDatas withUrl:#"push/iphone/registerdevice/"];
is this method deprecated?
You are getting nil in the identifier. So please check it like this
NSString *identifier = [dict stringForKey:#"identifier"];
if([identifier length] != 0)
[postDatas setObject:identifier forKey:#"device_uid"];
else
[postDatas setObject:#"" forKey:#"device_uid"];
You cannot put nil values into a dictionary. It will crash.
What you really need to investigate: Where do these nil values come from, and what is the appropriate thing to do when you get nil values? That's something only you can decide. Mukesh's answer should you how to store an empty string instead of nil. This avoids the crash. It often is the correct thing to do, but not always. So investigate what your app should do if one of the values is nil, and make it do exactly that.

iOS - Why does this NSString comparison blow-up? [duplicate]

This question already has an answer here:
Unrecognized selector error for isEqualToString: when setting text of a label
(1 answer)
Closed 8 years ago.
I have looked at SO for similar questions, but am open to being pointed to a duplicate.
I am receiving some JSON from a site, and I want to test for a 404 response.
I have this expression:
NSString *responseString = [json objectForKey:#"statusCode"];
NSLog(#"responseString: %#", responseString);
NSString *myString1 = #"404";
NSLog(#"%d", (responseString == myString1)); //0
NSLog(#"%d", [responseString isEqual:myString1]); //0
NSLog(#"%d", [responseString isEqualToString:myString1]); //Crash
The response string returns 404.
The first and second logs result in 0, and the 3rd crashes with this log:
[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0xb000000000001943
2015-01-29 16:23:33.302 Metro[19057:5064427] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0xb000000000001943'
statusCode is a number, not a string. The error makes this clear by telling you that you are trying to call isEqualToString on an NSNumber.
Try this:
NSInteger responseCode = [json[#"statusCode"] integerValue];
NSInteger notFoundCode = 404;
if (responseCode == notFoundCode) {
// process 404 error
}
The fact that you declared responseString as an NSString does not guarantee that [json objectForKey:#"statusCode"] will indeed return an NSString object.
Actually, the JSON parser detected an integer in your JSON data, and as such, returned an NSNumber. So you should be able to test it against a plain 404 literal using integerValue or, if you want to keep working with strings, will need to convert it first with stringValue.
Anyway, try this, it should return 1:
NSNumber *response = [json objectForKey:#"statusCode"];
...
NSLog(#"%d", [response integerValue] == 404);

How do I parse a csv file?

I'm trying to implement a label that shows me the current location's weather data as the following:
NSString *request = [NSString stringWithFormat:#"http://api.worldweatheronline.com/free/v1/weather.ashx?q=%#&format=csv&num_of_days=0&show_comments=no&key=myKeyThatIRemovedForThisQuestion",city];
NSURL *URL = [NSURL URLWithString:request];
NSError *error;
NSString *csv = [NSString stringWithContentsOfURL:URL encoding:NSASCIIStringEncoding error:&error];
NSArray *items = [csv componentsSeparatedByString:#","];
NSLog(csv);
NSLog([items firstObject]);
NSLog([items objectAtIndex:1]);
The logging line for the csv works.
The logging line for the first object in the array works.
But the objectatindex line throws an unexpected error:
libc++abi.dylib: terminating with uncaught exception of type
NSException
A sample of csv on console:
2014-02-27 21:27:43.626 Clock[1470:70b] 08:28 PM,17,116,http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png,Partly Cloudy ,9,15,100,E,0.2,59,16,1012,75
2014-02-27,18,64,8,46,13,22,169,SSE,263,http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png,Patchy light drizzle,3.8
How can I make this thing work so I can get my data from the array?
I've used Dave Delong's CSV parser a few times without issue. This can be found here: https://github.com/davedelong/CHCSVParser
It is also available via CocoaPods as CHCSVParser. This library has a test suite - and works fairly efficiently.

Using format specifier in for a URL in iOS

I'm having problems with using format specifiers for url's. Using the zBar scanner to scan a php link. I've spent a lot of time researching here on overflow but I cannot find the answer.
This is the code I use in my viewcontroller.m:
NSData *jsonData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://mywebsite.co.uk/TM.php?id=%#",self.scannedValue]]];
//NSData *jsonData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Sample" ofType:#"JSON"]];
NSArray *jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:Nil];
I'm trying to get the part after id to take in any integer number like 200,201,202,203,...
For some strange reason it only works when I type the number in itself as id=201 or id=202.
when I use NSLog for NSLog(#"%#",scannedValue) it shows the following:
2014-02-26 21:45:27.185 MeCombine[2412:60b] http://mywebsite.co.uk/TM.php?id=201
2014-02-26 21:45:27.277 MeCombine[2412:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil'
Can anyone tell me why this happens please?
A few notes:
scannedValue = sym.data;
is string, sum is ZBarSymbol class object
In the ZBarSymbol class
#property (readonly, nonatomic) NSString *data;
is the starting value.
When a value is successfully scanned it will return a NSString *data in the delegate method.
I can only provide a guess, since I don't see all of your code, but here's what I think goes on:
Your http link is malformed (http:: instead of http:). The jsonData object will be nil if it can't load the URL for whatever reason.
You don't do any null checking, and this nil object is sent to whatever method processes your json data, which throws a NSInvalidArgumentException if the data object is nil.
NSData's +dataWithContentsOfURL: does not tolerate nil URL, which in this case happens because of the incorrect URL format, notice you have two : in the URL after http. The correct URL would be.
http://mywebsite.co.uk/TM.php?id=%#
The modern and potentially more foolproof way of building URLs would be to use NSURLComponents (iOS 7 and OS X 10.9)
NSURLComponents *comps = [NSURLComponents componentsWithString:#"http://www.mywebsite.co.uk"];
comps.query = [NSString stringWithFormat:#"id=%#", self.scannedValue];
comps.path = #"/TM.php";
NSURL *URL = comps.URL;
The main benefit would be the ability to isolate the base URL into a constant string and then alter the query/path from elsewhere, both making things a bit more modular and easier to maintain than a hardcoded value in code.

Objective-c read image from sqlite

NSData *imageData = UIImageJPEGRepresentation(PhotoImage, 100);
NSString* queryString = ;
[SQLiteAccess insertWithSQL:
[NSString stringWithFormat:#"insert into images (photo) values ('%#')", imageData] // photo - blob column
]; // i use class SQLiteaccess
insert is normally
but when i read image from sqlite
NSArray *photoSelectArray = [SQLiteAccess selectManyRowsWithSQL: [NSString stringWithFormat:#"select photo from places where id=%i", idPlace]];
NSDictionary *imageDataDic = [photoSelectArray objectAtIndex:0];
NSData *dataForCachedImage = [[NSData alloc] initWithData: [imageDataDic objectForKey:#"photo"]];
UIImage *cachedImage = [UIImage imageWithData:dataForCachedImage];
i have an error - SIGABRT (Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString bytes]: unrecognized selector sent to instance 0x1e5c46d0')
p.s. class for easy access to sqlite
- SQLiteAccess.h - http://pastebin.com/BFxFry7T
- SQLiteAccess.m - http://pastebin.com/m67yNVLm
Yeah, I think the problem is here:
[NSString stringWithFormat:#"insert into images (photo) values ('%#')", imageData]]; // i use class SQLiteaccess
When using SQLite directly, you should set the binary data by sqlite3_bind_blob(), but you're actually setting the binary data as string.
So when you get back the data, it's not a binary data, it's a String object, of course, an string object don't response to -[NSData bytes]
Meanwhile I think you should check the field type in your SQLite DB file. Does the photo is actually set to blob.

Resources