iOS Get Connection - objective-c

This is my first time on this site and I am very new to coding so I was wondering if somebody could help me out.
I want to set a get request from my iphone app to my website and get the information echoed back from the website to my phone.
I have gotten this far but do not know where to go from here. Any help would be much appreciated, thanks!
- (void)myData:(id)sender
{
NSString *DataToBeSent;
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
[receivedData release];
receivedData = [[NSMutableData alloc] init];
DataToBeSent = [[NSString alloc] initWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php?Data=%#",sender];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];
[request setHTTPMethod: #"GET"];
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
[dataToBeSent release];
}
OLD WAY
- (void)myData:(id)sender
{
NSString *dataToBeSent;
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
[receivedData release];
receivedData= [[NSMutableData alloc] init];
dataToBeSent= [[NSString alloc] initWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php?Data=%#",sender];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent]];
Theconn= [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
NSLog (#"test1 %#", theRequest);
NSLog (#"test2 %#", Theconn);
[dataToBeSent release];
}
Then the following methods are called and I get my data BUT if I sent another request after my first one but different data on the same connection, it would always give me the same result which shouldn't happen
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
/* appends the new data to the received data */
[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
NSString *stringData= [[NSString alloc]
initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"Got data? %#", stringData);
[self displayAlertCode:stringData];
[stringData release];
// Do unbelievably cool stuff here //
}

Assuming your data loaded properly you can convert the data into a string and do whatever you want with it.
NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
//Make sure to set the correct encoding
NSString* responseString = [[NSString alloc] initWithData:response1 encoding:NSASCIIStringEncoding];
If your server returns JSON there are 3rd party libraries that can parse the string into collections like NSArray and NSDictionary. If your server returns XML then NSXMLParser could be something you can use.
EDIT
I've changed your code to manage the memory a little differently.
.h
#property (nonatomic,retain) NSMutableData * receivedData;
#property (nonatomic,retain) NSURLConnection * Theconn;
.m
#synthesize receivedData;
#synthesize Theconn;
//A bunch of cool stuff
- (void)myData:(id)sender
{
//If you already have a connection running stop the existing one
if(self.Theconn != nil){
[self.Theconn cancel];
}
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
//This will release your old receivedData and give you a new one
self.receivedData = [[[NSMutableData alloc] init] autorelease];
NSString *dataToBeSent = [NSString stringWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php? Data=%#",sender];
NSURLRequest *theRequest= [NSURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent]];
//This will release your old NSURLConnection and give you a new one
self.Theconn = [NSURLConnection connectionWithRequest:theRequest delegate:self];
NSLog (#"test1 %#", theRequest);
NSLog (#"test2 %#", Theconn);
}
//...
//Your delegate methods
//...
- (void) dealloc{
[receivedData release];
[Theconn release];
[super dealloc];
}

Related

Objective-C how to convert nsdata from web service to nsarray

How do i convert id to an array?
I have an apple app that talks to a server.
Issue i have is the app returns the data in the form of id however i need to convert this to an array as the actual returned data looks like the following.
[["30","2",1],["15","67",1],["30","4",1]]
It is actually the output from a mysql server
The actual app code looks like the following
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"blah blah"]];
NSURL_Layer * connection = [[NSURL_Layer alloc]initWithRequest:request];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err) {
//Need to convert the id to nsarray here, dunno how
} else {
//There was an error
}
}];
[connection start];
The NSURL.h
-(id)initWithRequest:(NSURLRequest *)req;
#property (nonatomic,copy)NSURLConnection * internalConnection;
#property (nonatomic,copy)NSURLRequest *request;
#property (nonatomic,copy)void (^completitionBlock) (id obj, NSError * err);
-(void)start;
NSURL.m
-(id)initWithRequest:(NSURLRequest *)req {
self = [super init];
if (self) {
[self setRequest:req];
}
return self;
}
-(void)start {
container = [[NSMutableData alloc]init];
internalConnection = [[NSURLConnection alloc]initWithRequest:[self request] delegate:self startImmediately:YES];
if(!sharedConnectionList)
sharedConnectionList = [[NSMutableArray alloc] init];
[sharedConnectionList addObject:self];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[container appendData:data];
}
//If finish, return the data and the error nil
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
if([self completitionBlock])
[self completitionBlock](container,nil);
[sharedConnectionList removeObject:self];
}
//If fail, return nil and an error
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
if([self completitionBlock])
[self completitionBlock](nil,error);
[sharedConnectionList removeObject:self];
}
Update:
i have added
NSURL_Layer * connection = [[NSURL_Layer alloc]initWithRequest:request];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err) {
NSError* error;
NSArray* array = [NSJSONSerialization JSONObjectWithData:obj options:NSJSONReadingAllowFragments error:&error];
} else {
//There was an error
}
}];
[connection start];
but returns error
error NSError * domain: #"NSCocoaErrorDomain" - code: 3840
_userInfo NSDictionary * 1 key/value pair
[0] (null) #"NSDebugDescription" : #"Invalid value around character 0."
Update: I put
NSLog(#"Data as string:%#", [[NSString alloc]initWithData:obj encoding:NSUTF8StringEncoding]);
which gave me a strange feedback. As a result i looked at my url request full code is below.
NSString *post = [NSString stringWithFormat:#"unique_id=%#&unique_password=%#",ServerUniqueID,ServerPassword];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[post length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"blah blah"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSURL_Layer * connection = [[NSURL_Layer alloc]initWithRequest:request];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err)
{
NSError* error;
NSArray* array = [NSJSONSerialization JSONObjectWithData:[NSData dataWithData: obj] options:NSJSONReadingAllowFragments error:&error];
NSLog(#"Data as string:%#", [[NSString alloc]initWithData:obj encoding:NSUTF8StringEncoding]);
int temp = array.count;
}
else
{
//There was an error
}
}];
[connection start];
if i remove
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
it works
if its in it dosn't so i have a whole new issue to look into.
you save the bytes into a container variable, alas the id infact NSData
(note id is just a 'wildcard pointer' that means ANY objC object)
so your id is NSData and from what you show it seems to be 3 json arrays... but no real JSON... (["30","2",1]["15","67",1]["30","4",1] isn't anything)
EITHER make the server send you JSON and THAT you can parse into a dictionary/array using NSJSONSerialization
OR write a custom separator to convert the data

Slow Multiple URL retreival in iOS code

I want to access a URL and retrieve data from this URL, based on the data retrieved I want to retrieve data from another URL
I tried accessing multiple URL in the following way:
- (void) showClassRoom:(NSString *)theMessage{
NSString *queryURL =[NSString stringWithFormat:#"http://nobert.cloudfoundry.com/CalOfEvents/tos"];
NSURL *url = [NSURL URLWithString: queryURL];
NSURLRequest *req = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSError *error;
NSURLResponse *response;
NSData *returnData = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];
if(returnData){
NSString *strResult = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];
NSDictionary *result = [strResult JSONValue];
for(id theKey in result){
for(id hello in theKey){
NSLog(#"The key:%#, The value:%#",hello,[theKey objectForKey:hello]);
}
}
if(TRUE){//based on some condition secondShowClassRoom is called
[self secondShowClassRoom];
}
}
}
- (void) secondShowClassRoom{
NSString *queryURL =[NSString stringWithFormat:#"http://nobert.cloudfoundry.com/CalOfEvents/to"];
NSURL *url = [NSURL URLWithString: queryURL];
NSURLRequest *req = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSError *error;
NSURLResponse *response;
NSData *returnData = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];
if(returnData){
NSString *strResult = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];
NSDictionary *result = [strResult JSONValue];
for(id theKey in result){
for(id hello in theKey){
NSLog(#"The key:%#, The value:%#",hello,[theKey objectForKey:hello]);
}
}
}
}
This retrieves the data VERY SLOWLY and my app requires very fast access as I am developing an application on Augmented Reality
There is another method that is faster however I am not able to access multiple URLs:
- (void) showClassRoom:(NSString *)theMessage{
NSString *queryURL =[NSString stringWithFormat:#"http://nobert.cloudfoundry.com/CalOfEvents/to"];
NSURL *url = [NSURL URLWithString: queryURL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn) {
webData = [[NSMutableData data] retain];
}
classRoomControl.hidden = NO;
labControl.hidden = YES;
placementControl.hidden = YES;
}
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *) response{
[webData setLength: 0]; }
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *) data {
[webData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *) error {
[conn release];
[webData release];
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
[conn release];
NSLog(#"DONE. Received Bytes: %d", [webData length]);
NSString *strResult = [[NSString alloc] initWithBytes:[webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
NSDictionary *result = [strResult JSONValue];
for(id theKey in result){
for(id hello in theKey){
NSLog(#"The key:%#, The value:%#",h,hello);
}
}
[strResult release];
[webData release];
}
Please Help me with this.Any help would be appreciated..
You are right on track preferring the asynchronous model for network communication (since synchronous communication will block your UI unless you handle it in a separate thread).
The correct way to chain multiple asynchronous network request is doing one request after another in the callbacks (i.e., in connectionDidFinishLoading; when one request is done, you send the next one).
One more suggestion is not using NSURlRequest/NSURLConnection for that, since they make thinks unnecessarily complex, and try with a framework like AFNetworking.

Get web service response data

I have made this so far. It's code that will make a json String request with an http Header. When i run this code i get no errors. But i get a Expression result unused warning. I should get a response from the web service after sending this http header.
code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *nid = #"";
NSString *vocab = #"";
NSString *inturl = #"testoverview";
NSString *mail = #"chh#fbr.dk";
NSString *md5pw = #"4d57e7ef1b7c3f431aca424764e9d786";
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
nid, #"nid",
vocab, #"vocab",
inturl, #"inturl",
mail, #"mail",
md5pw, #"md5pw",nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (!jsonData) {
NSLog(#"Got an error; %#", error);
} else if(jsonData) {
NSString *url = #"http://www.taenk.dk/services/mobile";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
[request setValue:jsonString forHTTPHeaderField:#"X-FBR-App"];
[[NSURLConnection alloc] initWithRequest:request delegate:self]; <-- this line triggers the warning: "Expression result unused"
NSLog(#"jsonString %#", jsonString);
}
Can anybody clarify 2 things for me:
Does this trigger a response as soon as the request to the web service?
If yes, how do i print this result out?
You need to assign the result to a variable like
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:...
for later use (e.g. [con cancel];)
Then you should at least implement the delegate method connection:didFailWithError:. In the class reference I don't see the connection:didFinishLoading... anymore. Can you use the sendSynchronousRequest:returningResponse:error: instead, then you'll have the result, be it positive or negative.
This is how I retrieved the data (this version is without ARC):
- (void) connection :(NSURLConnection *)conn didReceiveData :(NSData *)data {
NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[self checkAutoMailReply:msg];
[msg release];
}
msg contains the pure response data, no header or such.

How to get an array from NSMutableData

I have text file with 5 strings. I need to use NSURLConnection to get contnent of this file. But NSLog shows me, that 'dump' is empty. How can I transform the data from NSMutableData to NSArray. Arrays is because I need to show those 5 items in a TableView.
NSURLRequest *theRequest=[NSURLRequest
requestWithURL:[NSURL URLWithString:#"http://dl.dropbox.com/u/25105800/names.txt"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
receivedData = [NSMutableData data];
NSString *dump = [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"data: %#", dump);
NSArray *outputArray=[dump componentsSeparatedByString:#"\n"];
self.namesArray = outputArray;
Thanks in advance. BTW URL works, you can see the file.
Here's how you implement this solution with a delegate:
In your .h file:
#interface MyClass : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
#property (nonatomic, retain) NSMutableData *receivedData;
#property (nonatomic, retain) NSArray *namesArray;
#end
In you .m file:
#implementation MyClass
#synthesize receivedData = _receivedData;
#synthesize namesArray = _namesArray;
- (id)init {
self = [super init];
if (self) {
self.receivedData = [NSMutableData data];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://dl.dropbox.com/u/25105800/names.txt"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
[connection start];
}
return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Received response! %#", response);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *dump = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding];
NSLog(#"data: %#", dump);
self.namesArray = [dump componentsSeparatedByString:#"\n"];
}
#end
If you don't want to use a delegate, you can use a synchronous call with NSURLConnection, like this:
NSURLRequest *theRequest=[NSURLRequest
requestWithURL:[NSURL URLWithString:#"http://dl.dropbox.com/u/25105800/names.txt"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSError *error = nil;
NSHTTPURLResponse *response = nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:theRequest response:&response error:&error];
if (error == nil) {
NSString *dump = [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"data: %#", dump);
NSArray *outputArray=[dump componentsSeparatedByString:#"\n"];
self.namesArray = outputArray;
}
Just beware that this will not be running asynchronously. If you don't want it to run on the main thread and block your main thread/UI, consider using a separate thread to execute that code or use GCD.
You have to use the delegate, then save the received data into receivedData (which is of course empty right now.. you just initalized it.) and then you transform the data into a string, like you did it in your example. Have a look at NSURLConnectionDelegate
You need to implement the delegate methods for NSURLConnection to be notified of incoming data. You are using the asynchronous methods.
Also note that [NSMutableData data] just creates an empty data-object.. so you can't expect it to contain any data..
I suggest you read https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html#//apple_ref/doc/uid/20001836-BAJEAIEE
(completely!)

Spin screen with connection

I would like to know how to do the next:
I have one app that make some connections to receive data (this data is shown in the screen)
I would like to know which code I can use to wait each connection, I mean, the time between the connection start and this finish I would like to show in the screen one spin (Loading...).
I have created the connections, and the spin. My problem is that I don't know which code I can use to manage this and where to write this code.
You should look at using NSURLConnection with a delegate. An NSURLConnection lets you get data from a server asynchronously (it runs in the background, and notifies the delegate when certain events happen).
Then, in your view controller class, you can start the spinner right before you launch the connection, and have one of your delegate methods stop the spinner when the connection finishes.
this is my code in the class: Connection.h, and i create an object Connection in every class where i want to call a new connection to get data (i don't know then if this is the correct way to do)
import "Connection.h"
import "XMLParser.h"
#implementation Connection
#synthesize webData, soapResults, xmlParser;
-(Connection *) Init:(NSInteger *) methodNumber{
[super init];
methodNum = methodNumber;
return self;
}
-(void)Connect:(NSString *) soapMessage{
NSLog(soapMessage);
NSURL *url = [NSURL URLWithString:#"http://.....?WSDL"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMessage length]];
[theRequest addValue: #"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
//NSURLConnection *theConnection = [NSURLConnection connectionWithRequest:theRequest delegate:self];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
[theConnection start];
if( theConnection )
{
webData = [[NSMutableData data] retain];
}
else
{
NSLog(#"theConnection is NULL");
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConenction");
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
NSLog(theXML);
[theXML release];
if( xmlParser )
{
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData: webData];
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser:methodNum];
//Set delegate
[xmlParser setDelegate:parser];
//[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
[connection release];
[webData release];
}
#end