How to use json data from localhost in objective-c? - ios

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSURL *site_url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/json/data/post?sid=%#", SECURE, PASSCODE]];
NSData *jsonData = [NSData dataWithContentsOfURL:site_url];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.items = dataDictionary;
}
I am trying to parse json data. It works fine with data from the live server. However, when I change the link to http://localhost:8090. It stops working.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil'
I can access it from the data from the web browser. Does anyone know why is that?

Does it work on emulator and not on a real device?
You should never use localhost when developing apps, use the local IP for the server instead. Localhost is the machine who make the call to the server. When you try on the emulator and you have the server on the same machine it works because they are the same.
But when you try on a real device, localhost is the device, and the device doesn't have a server installed, so it will fail.
BTW, to test on a real device, it has to be connected to the same network.

What you need here is to implement the NSURLConnection and receive data from it
Check out this
NSURL *site_url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/json/data/post?sid=%#", SECURE, PASSCODE]];
NSURLRequest *req = [NSURLRequest requestWithURL:site_url];
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:req delegate:self];
[con start];
and from the delegates get the response
this document can help you a lot in this

Related

How to set pass api key within NSURLRequest in iOS?

as of now I have it like so:
NSURLRequest *Request = [NSURLRequest requestWithURL:[NSURL URLWithString: reqURLStr]];
NSURLResponse *resp = nil;
NSError *error = nil;
NSData *response = [NSURLConnection sendSynchronousRequest: Request returningResponse: &resp error: &error];
NSString *responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
return responseString;
and I call it like so:
NSString *stripeCustomerRequestURL = [NSString stringWithFormat:#"https://api.stripe.com/v1/customers/%#",stripeCustomerId];
// NSString for the return of the tax in decimal form
NSString *customerInformation = [self retrieveStripeCustomer:stripeCustomerRequestURL];
I am getting this error which I know I need to pass the api key but how can I?
{
"error": {
"type": "invalid_request_error",
"message": "You did not provide an API key. You need to provide your API key in the Authorization header, using Bearer auth (e.g. 'Authorization: Bearer YOUR_SECRET_KEY'). See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/."
}
}
It is not considered secure to be using your Stripe Secret API key from code that runs on a client device (iOS / Android apps, desktop apps, etc). As soon as you include your API key in a shipped binary, you can assume someone will inspect your binary and be able to extract the strings from it, including your API key thus compromising it.
Your API key should only be used on a server that you control. Your iOS app can call endpoints on your server and in turn your server will call out to Stripe.

NSURLCache not working after iOS app termination

I am building an app in which I am implementing offline mode as well. For this I used NSURLCache mechanism. When the app is in foreground then the cache mechanism works perfectly even if the device goes in offline mode. The problem comes when I quit the app and then open it in offline mode. This time NSCachedURLResponse is returning nil for the particular request.
Below is the code I am using for this:
Custom Cache Creation:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:1024*1024 diskCapacity:1024*1024*5 diskPath:nil];
[NSURLCache setSharedURLCache:urlCache];
}
Calling server and cached object:
-(void)serverCall
{
NSURLCache *urlCache = [NSURLCache sharedURLCache];
NSString *urlString = nil;
NSHTTPURLResponse *response = nil;
NSError *error = nil;
urlString = [NSString stringWithFormat:#"%#%#",BASE_URL,url];
urlString = [urlString stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSURL *finalUrl = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:finalUrl];
request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
NSData *data = nil;
if ([self checkInternetConnection])
{
data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data];
[urlCache storeCachedResponse:cachedResponse forRequest:request];
}
else
{
NSCachedURLResponse *cachedResponse = [urlCache cachedResponseForRequest:request];
response = cachedResponse.response;
data = cachedResponse.data;
}
}
I can see that caches.db in library path of application the response is saved. But when i am trying to read it in Offline mode (after app is killed from background), the cached response is coming nil. I have gone through following links (and many more) but couldn't find the solution of my problem.
NSURLCache Problem with cache response
How to use NSURLCache to return cached API responses when offline (iOS App)
http://twobitlabs.com/2012/01/ios-ipad-iphone-nsurlcache-uiwebview-memory-utilization/
http://petersteinberger.com/blog/2012/nsurlcache-uses-a-disk-cache-as-of-ios5/
Bypassing http response header Cache-Control: how to set cache expiration?
I have checked the http header fields and cached header in the api response and the problem is not from server end.
I have also tried providing a path in diskPath param while creating the custom cache but then it doesn't even load the cached object while the app is in foreground and internet disconnects. I have also changed the expiration date but the working is still same.
I have tried using SDURLCache but I am facing the similar problem. However I have successfully achieved this with ASIHTTPRequest but I don't want to use it as I have written all the server operations once already and I have to change every request with ASIHTTPRequest method.
Please help me find a solution for this.
Thanks in advance....

NSData dataWithContentsOfUrl: loads outdated data

In my app I load some static JSON string from some server.
Every now and then the JSON file is updated and then I want the app to reload the data.
Now, that I updated the file on the server the app does not reflect the change. If I take the URL to that file from the app's code and copy it into a browser and fetch the file there, I clearly see the updates. But when I run the app and log the json string to the debug console, then I clearly see an outdated version of the file's content.
Is there any caching involved? Can I force the iOS to actually reload it?
This is how I load it now:
NSURL * url = [NSURL URLWithString:[DOWNLOAD_URL stringByAppendingString:DOWNLOAD_FILE]];
NSError * error;
NSData *jsonData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
NSLog(#"JSON: %#", [NSString stringWithUTF8String:[jsonData bytes]]);
The option NSDataReadingUncached should prevent the system from caching the data.
PS: When I run the app on a different device, then it receives the current data. But when I again let it run on the original device - on which I observe this behaviour - then the data "received" is still outdated. So it really looks like some cashing issue to me.
Here is an idea. Try calling
[[NSURLCache sharedURLCache] removeAllCachedResponses];
For more granular control on cashing use NSURLConnection or NSURLSession.
I did try Mundi's suggestion, to try clearing the cache, but this didn't make any difference in my iPhone app.
So, I tried a trick which I use in my Angular webapps, and appended the current time (in ticks) to the URL I'm attempting to open, and that did work:
NSString* originalURL = #"http://somewebservices/data/1234";
NSString* newURL = [NSString stringWithFormat:#"%#?t=%f", originalURL,
[[NSDate date] timeIntervalSince1970]];
NSLog(#"Loading data from: '%#'", newURL);
NSURL *url = [NSURL URLWithString:newURL];
if (url == nil)
return false;
NSError *error;
NSData* urlData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
(Sigh.)
I'm getting too old for this stuff....

StoreKit verification error 21002: The data in the receipt-data property was malformed

On a iPhone 4/iOS 4 device, sandbox App Store is reporting this error during verification:
21002: The data in the receipt-data property was malformed.
On a iPhone 5/iOS 6 device, the same code works (status == 0, receipt returned) without any problems.
I've restarted the device, made sure the Apple ID is logged out, even made a new test user account. Same result. Any ideas?
This Error means the JSON Object that you have created to send for verification is not in correct format.
{
"receipt-data" : "(receipt bytes here)"
}
So My suggestion is to Debug the same on iPhone 4/iOS 4. In case, you are Using Json Framework to create JSON object (for receipt validation) it will work only with iOS 5.0 & above.
Adding Code I had Implemented a few months I Used SBJson to write N parse.
NSString *base64TxReceiptStr=[NSData Base64Encode:transaction.transactionReceipt];
SBJsonWriter *writer = [[SBJsonWriter alloc] init];
NSDictionary *command = [NSDictionary dictionaryWithObjectsAndKeys:
base64TxReceiptStr, #"receipt-data",
nil];
NSString *jsonString = [writer stringWithObject:command];
NSData *requestBody=[jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *txReceiptVerificationRequest=[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"https://sandbox.itunes.apple.com/verifyReceipt"]];
[txReceiptVerificationRequest setHTTPBody:requestBody];
[txReceiptVerificationRequest setHTTPMethod:#"POST"];
NSURLResponse *response=nil;
NSError *error=nil;
NSData *responseData=[NSURLConnection sendSynchronousRequest:txReceiptVerificationRequest returningResponse:&response error:&error];
NSString * receivedString=[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *aobject =[parser objectWithString:receivedString];`
For your sandbox environment use: https://sandbox.itunes.apple.com/verifyReceipt
For actual verification use: https://buy.itunes.apple.com/verifyReceipt
You can check this at Apple's official page.

NSURL Request? Registration and Login

Here is my code:
//login method
- (int) authenticateClient {
NSString *loginWeb = [NSString stringWithFormat:(#"http://192.168.118.1/login.php?uname=%#&pass=%#&submit=Log%%20In"), user, pass];
NSURL *login = [NSURL URLWithString:loginWeb];
NSData *loginData = [NSData dataWithContentsOfURL: login];
NSString *result = [[NSString alloc] initWithData:loginData encoding:NSUTF8StringEncoding];
NSMutableURLRequest *loginRequest = [[NSMutableURLRequest alloc] init];
[loginRequest setURL:login];
[loginRequest setTimeoutInterval:1];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:loginRequest delegate:self startImmediately:YES];
[connection start];
return [result integerValue];
}
My question is, when simulating having no network connection, my app freezes up and doesn't load or time out in the specified interval (1 second just to see if it works).
I read something about start immediately forces in to run on the current threat causing everything else to "pause" until the action is complete.
I have two questions:
1.) What is a better method to have the URL basically run in the background instead of pausing everything?
2.) How can I get a timeout method that actually works?
Much appreciation! Thanks!
Well, one second as timeout is really low. If you want to simulate different network conditions, you can use something like this. You don't need to this dance:
NSData *loginData = [NSData dataWithContentsOfURL: login];
NSString *result = [[NSString alloc] initWithData:loginData encoding:NSUTF8StringEncoding];
You don't need this as well, since the connection has started already:
[connection start];
Also from the documentation:
NSURLConnection’s delegate methods—defined by the
NSURLConnectionDelegate Protocol protocol—allow an object to receive
informational callbacks about the asynchronous load of a URL request.
Other delegate methods provide facilities that allow the delegate to
customize the process of performing an asynchronous URL load. These
delegate methods are called on the thread that started the
asynchronous load operation for the associated NSURLConnection object.
So for your questions:
Implement the NSURLConnection’s delegate
Check this & this.

Resources