I am trying to implement a simple TTURLRequest in my app. I'm pretty new to the Three20 framework. I mainly want TTURLRequest and TTImageView for the awesome caching stuff.
I have the following code in my delegate:
- (void)requestDidFinishLoad:(TTURLRequest*)request {
TTURLDataResponse *response = request.response;
// Stuff to process response.data
}
response is always nil. I can't figure out what I'm doing wrong. I looked in the Application Support directory and it's creating the cache file with the proper data, so I know it's getting a response. What am I doing wrong?
Debugged your code - you actually have to create a response object and add it to the request before sending your request:
NSString *url = #"http://twitter.com/statuses/user_timeline/samsoffes.json?count=1";
TTURLRequest *theRequest = [[TTURLRequest alloc] initWithURL:url delegate:self];
theRequest.response = [[[TTURLDataResponse alloc] init] autorelease];
[theRequest send];
One would think the request would be in charge of creating the response, but the Three20 stuff doesn't.
Mark Allen from revetkn.com posted a datasource implementation for TTURLRequest.
He also posted an example project where he assumes you have Three20 installed at ../ (relative to your project). It's here: http://revetkn.com/?p=72
Related
This is a tough question.
When I press on the button, it is supposed to connect to a URL, which will initiate that method of my wcf service. However, when I debug, I noticed that the connection fails (like none of the delegate methods are called and stuff). I know that my WCF service works because when i type the URL in safari directly, it works perfectly, and performs that method. Here is my code:
- (IBAction)RBCButtonPressed:(id)sender {
//[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"http://10.1.51.55:8732/windows2/OnApplication?appName=RoyalBank.BankOfTheFuture.Surface.exe&directory=C:\\Program Files (x86)\\Bank of the Future"]];
NSString *urlString = #"http://10.1.51.55:8732/windows2/OnApplication?appName=RoyalBank.BankOfTheFuture.Surface.exe&directory=C:\\Program Files (x86)\\Bank of the Future";
NSLog(urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url ];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
if(connection)
self.valueReturned = [[NSData data] retain];
else
NSLog(#"data failed");
NSLog(#"connection failed");
[captureView addSubview:loader];
}
I'm not including the delegate methods cause they aren't called anyway.
It prints "connection failed."
UPDATE: When I use a method that takes in only one parameter, it works fine from both the browser and the device (the connection succeeds and the delegate methods are called). However, when there are two parameters, it works fine only from the browser. The connection always fails.
Possibilities - the use of the backslash confuses it somehow (?).
This is urgent and any help would be greatly appreciated.
EDIT: It will always print "connection failed" I realize, but I know that the connection fails because 1) the delegate methods aren't called and 2)the application does not turn on, which it will if the method is called.
If you check your NSURL object in the debugger, you'll find it's nil immediately after you try to initialize it. This is because it's malformed. Try URL encoding it first.
Notice the URL you pasted into safari changes to this:
http://10.1.51.55:8732/windows2/OnApplication?appName=RoyalBank.BankOfTheFuture.Surface.exe&directory=C:%5C%5CProgram%20Files%20(x86)%5C%5CBank%20of%20the%20Future
See all the %20s and %5Cs, etc.? That's because safari URL encodes it before sending the request. You must do the same.
Best regards.
It's failing because you are releasing connection right after you create it. If you're not using ARC, you could create it with autorelease, or just use ARC and forget about the releases.
I am new to objective-c. I load the whole xml string from server to an nsxml parser like below: but the problem is loding from url to memory takes much more time than parsing it. how can i solve that? (my app is very slow)
xmlString = [[NSMutableString alloc] initWithContentsOfURL:url usedEncoding:&NSUTF8StringEncoding error:&error];
NSData *xmlData = [xmlString dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
Run your XML Parser in different Thread.(this will not make your parsing faster)
How To Choose The Best XML Parser for Your iPhone Project
Basically NSXMLParser is slow. There is a possibility of finding a better parser for the specific need. A true stream parser might help if you do not need the entire DOM and validation.
Don't use
xmlString = [[NSMutableString alloc] initWithContentsOfURL:url usedEncoding:&NSUTF8StringEncoding error:&error];
Use a network library like ASIHTTPRequest to load the content from a URL and then parse it.
Loading directly from URL like you've done will hang your app till the data is loaded.
Download and install that library as given in the instructions (it's easy), then you can do
{
//in some function
NSURL *url = [NSURL URLWithString:urlString];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous]; //this will load URL in background
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
//parse the XML here
[self parseXML:responseString];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
You cannot load the xml faster from the url as it totally depends on your internet connection.
To keep your application smooth, you need to parse the xml in another thread. I answered a similar question in the following url
How to handle freezing programm at loading xml from bad url?
Also there are faster XML parser than the defaul NSXMLParser. There is a good introduction about them in the following blog post. So you can use any of these parser in place of NSXMLParser to improve the performance of your application.
http://www.raywenderlich.com/553/how-to-chose-the-best-xml-parser-for-your-iphone-project
I hope that it may clarify a little bit of your question.
I am using stringWithcontentsofurl to download some strings from my web server to the App, but i would like to update the UI to show A loader of some kind. I am downloading a number of strings (it can be sometimes as much as 100) so it would be neat for the user to show something so they know the App isn't crashing, because now the UI is stuck, i can't show A UILoader or something like that. Is there an option to do so? Or maybe A alternative to stringWithcontentsofurl where this is possible?
greets,
Erik
Try this. It loads stuff in background. If updating the UI later (in asyncload), be sure to do that on main thread.
-(void)loadappdetails:(NSString*)appid {
NSString* searchurl = [#"https://itunes.apple.com/lookup?id=" stringByAppendingString:appid];
[self performSelectorInBackground:#selector(asyncload:) withObject:searchurl];
}
-(void)asyncload:(NSString*)searchurl {
NSURL* url = [NSURL URLWithString:searchurl];
NSError* error = nil;
NSString* str = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (error != nil) {
NSLog(#"Error: %#", error);
}
NSLog(#"str: %#", str);
}
This is a classic case for "Lazy Loading". See Apple's example code:
http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
It should be easy to substitute "strings" for "images" as you read that code.
You want to display a placeholder in the label like "(fetching information)" or similar and then load the information in the background, either threading the fetches yourself (asynchronous fetching) or using a library like ASIHTTPRequest that handles all the asynchronous nuts and bolts for you, calling a delegate method once the fetch has completed.
Unfortunately, stringWithContentsOfURL is a synchronous method, meaning it will block your thread and you will not receive any callbacks while it is running. This is also bad for user experience.
The alternative would be to use NSURLConnection to manually setup your own request, and tap into the delegate methods of your connection to display some sort of progress bar. Specifically, you'll want to use connection:didReceiveData: and connectionDidFinishLoading:
Once all the data has been received, use the following to get your string.
NSString *theString = [[NSString alloc] initWithData:yourData encoding:UTF8StringEncoding];
To make this method asynch it is possible and recommendable to use Grand Central Dispatch. If anyone is interested I will show the few lines of code to do that.
First of all, sorry for my posibly bad english...
I got a surely big stupid question...
In my enterprise have an automatic door system, that is opened with a HTTP GET request to a file.
Example:
http://ipaddress/rc.cgi?o=1,50
Where the o=number indicates the amount of seconds that the automatic door will run.
The is no need for authentification or nothing (that is made by LAN Radius).
So, the question is...
How can I make a single button (for example in the springboard) that when you touch it, runs the GET request?
You thing that it should be possible with NSURLConection ?
Thanks for all
I'm not sure if this is the best way of going about it, but this is how I've achieved something similar in my own app. Just create a new NSData object that hits the required URL, then release it if you don't need to do anything with the returned data:
NSURL *theURL = [[NSURL alloc] initWithString:#"http://ipaddress/rc.cgi?o=1,50"];
NSData *theData = [[NSData alloc] initWithContentsOfURL:theURL];
[theData release];
[theURL release];
Or just create an NSURLConnection to run asynchronously, then you don't have to worry about the UI hanging and if the delegate is set to nil, you can pretty much forget about it after you've run it.
NSURL * url = [NSURL URLWithString:#"http://ipaddress/rc.cgi?o=1,50"];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:url];
NSURLConnection * theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:nil];
[request release];
[theConnection release];
I'm sorry if this is a basic question. I've been googling, searching StackOverflow, and looking through example code for hours and haven't found anything satisfactory for my skill level.
I'm wanting something like a design pattern for handling network functions on the iPhone SDK. I have heard of people using a singleton class but have heard there are better ways for asynchronous connections. Would NSOperation be useful? I am fairly new to object oriented programming but am needing to make occasional calls to my webserver through HTTP for my current app and hope to find a solution that is easily reusable.
I've looked through the NSURLConnection docs and can get the basic functionality but the programming structure is messy and I'm not sure how to better organize it. Is there sample code for this that separates out these functions into their own class? A link to an example that does this would be greatly appreciated!
thanks!
I've been dealing with this same question for a while now...
If you're effectively doing a GET on a simple resource, and you're confident that the resource will always be there & accessible, there's an easy way to do it:
NSURL *URL=[[NSURL alloc] initWithString:#"http://www.google.com/"l];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
//TODO This needs to have timeouts & such set up, maybe parallelism
NSString *results = [[NSString alloc] initWithContentsOfURL :URL];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
That's a REALLY simple way to do it, but as my comment says, not very robust or reliable.
A slightly more robust, yet still reasonably simple, is replacing the NSString line with:
results = [[NSString alloc] initWithContentsOfURL:URL encoding:NSASCIIStringEncoding error:&err]; // possibly NSUnicodeStringEncoding
if (err!=nil) NSLog(#"Error occurred: %#", [err localizedDescription]);
That will at least TELL you if there's an error...
ASIHTTPRequest provides a lot of neat & useful network functionality for dealing with resources over the internet. http://allseeing-i.com/ASIHTTPRequest/ - the developer has been VERY responsive on his Google Group. I really wanted to use that, and may get back to it when/if it supports SSL Client Certificate authentication (which is what my project requires).
NSURLConnection, as described above - that's what I'm using now in my project. I would imagine that this will satisfy almost all needs, but it's (in my opinion) more tricky to use. And to be honest, I'm still having a little trouble wrapping my mind around how to integrate asynchronous data loading into my application. But if it will work for you - and it probably will, Apple is using it all over the OS and its apps - that's your best bet!
One possible approach is to use the NSURLConnection (as you mentioned).
Inside your .h file:
NSMutableData *connectionData;
Also add a property for connectionData...
Inside your .m file:
- (void)updateFromServer {
// You might want to display a loading indication here...
NSMutableData *connectionDataTemp = [[NSMutableData alloc] init];
self.connectionData = connectionDataTemp;
[connectionDataTemp release];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: your_url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
}
#pragma mark -
#pragma mark NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Add the received bulk of data to your mutable data object
[self.connectionData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Use your data
// If there is a loading indication displayed then this is a good place to hide it...
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// Handle error
// If there is a loading indication displayed then this is a good place to hide it...
}