Create a new delegate class for each asynchronous image download? - iphone

First, I'm using an NSURLConnection to download JSON data from twitter. Then, I'm using a second NSURLConnection to download corresponding user avatar images (the urls to the images are parsed from the first data download).
For the first data connection, I have my TwitterViewController set as the NSURLConnection delegate. I've created a separate class (ImageDownloadDelegate) to function as the delegate for a second NSURLConnection that handles the images. After the tweets are finished downloading, I'm using this code to get the avatars:
for(int j=0; j<[self.tweets count]; j++){
ImageDownloadDelegate *imgDelegate = [[ImageDownloadDelegate alloc] init];
Tweet *myTweet = [self.tweets objectAtIndex:j];
imgDelegate.tweet = myTweet;
imgDelegate.table = timeline; //to reload the data
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:myTweet.imageURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60];
imgConnection = [[NSURLConnection alloc] initWithRequest:request delegate:imgDelegate];
[imgDelegate release];
}
So basically a new instance of the delegate class is created for each image that needs to be downloaded. Is this the best way to go about this? If I were to create only one instance of the delegate class there's no way to figure out which image is associated with which tweet, correct? Nor would I be able to figure out the exact order in which the images are being downloaded.
The algorithm works fine... I'm just wondering if I'm going about it the most efficient way .

Put image downloads into something like an NSOperationQueue.
When the image download is done, save it to the caches directory, then send out a notification containing the original image URL, and the filename the image is now located at.
Anything that wants the image can listen for the notification. If nothing cares anymore (say cells that have scrolled off the screen) then they will have unsubscribed from notifications, so the image will just sit there until the system cleans out your cache directory...
It's also trivial with this system to check and see if an image already exists on disk before you download it, just keep somewhere a mapping of URL's to filenames.

You might perhaps use the queuing feature of ASIHTTPRequest instead. You can create an ASINetworkQueue to handle a ordered queue of requests, and each request can perform behaviors on completion, so that you can track requests with responses.
Requests are based on the NSOperation class, and the queue on NSOperationQueue, so this framework does a lot of the coding work for you.

Related

How to use NSOperationQueue to download audio files from server one by one

I have an array containing audio file url's. I want to fetch audio files from server using these url's in background mode. I have heard that i can achieve this with NSOperationQueue. My query is
1)How can i achieve this.
2)How can i get call back on single operation completion/failure
3)How can i get call back after completion of the whole process.
I need these call backs to keep track of downlaod process so that i can update my database about the download status of files. So, in case any internet connection loss i can download the remaning files again.
Any idea will be helpful as i am new to NSOperationQueue.
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(download:) object:aAudio];
[queue addOperation:operation];//added code
[operation release];
now do stuff what u want in method download. as per doc set [queue setMaxConcurrentOperationCount:1] for one by one.
Seems like AFNetworking has all that you need (callback blocks for success / failure, puttings requests in NSOperationQueue). In your case probably AFHttpClient and its enqueueHTTPRequestOperation method will do the job.

UIWebView loading and general performance

I am using UIWebView to display textual content in my app (I store the content in local HTML files that I pack with the app). All together, I have three web views whose content I change dynamically based on user feedback.
Although some might argue that this is not the most accepted way, I find UIWebView very convenient to display formatted text, and modify that text using HTML if necessary. While this works 99% of the time, on occasion, I experience problems that generally fall into one of these categories:
Sometimes, the web view content loads slow and is late a second or so.
The content loads but is not showing. However, as long as, I touch the view (try to scroll or something) the content pops in.
A few times I received memory warnings (usually not long after the app's initial loading) that in no way affected the performance of my app. It logged the memory warning but the app worked like nothing happened.
This is the method I use to load content to my web views:
- (void)loadSimpleDocument:(NSString*)documentName inView:(UIWebView*)webView
{
NSString *path = [[NSBundle mainBundle] pathForResource:documentName ofType:#"html"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
Aside from this, the shouldStartLoadWithRequest delegate method is also implemented, always returning a YES.
My question is: Is there a way to improve the reliability/performance of my web views (in particular loading)? Is there something I have overlooked, did wrong, or do not know about?
Some additional info:
I am on iOS6 SDK, use ARC, and do everything programmatically (do not use IB or storyboard).
You have 2 options to check what's going on:
Implement webViewDidStartLoad & webViewDidFinishLoad delegate methods to check why the content isn't showing (may be the content isn't loaded yet).
read the html content to an NSString then use loadHTMLString:baseURL instead of using loadRequest and check if it loads faster.
Hope this could help.

Progress bar not showing accurate progress

In my app i am getting data from server and saving in SQLite table. i have to show the progress bar for this entire process. I wrote [myRequest setDownloadProgressDelegate:progressView]; but it is working up to downloading the data from server only,it is not showing the progress for saving data in to the SQLite table. please help me. Thank you
Here is some code i wrote before calling the url,in the request finishing method i am saving the entire data in to SQLite.
if (!myQueue)
{
myQueue = [[ASINetworkQueue alloc] init];
}
[myQueue reset];
[myQueue setDownloadProgressDelegate:progressView];
[myQueue setShowAccurateProgress:YES];
[myQueue setDelegate:self];
ASINetworkQueue will only update the progressView up to downloading the data from server, Because ASI classes are for making connection with server , downloading source , make a queue of requests etc.
After the class had informed you that data is fully downloaded ASINetworkQueue's work is finished and after that it is your application's responsibility to show the progress of saving the data in db

how to show loading image indicator inside uitable?

i'm new using Trhee20 in Xcode and i'm building an APP that needs to send a post request to a page to register a new user using the following code:
TTURLRequest *request = [TTURLRequest requestWithURL:page delegate:self];
request.httpMethod = #"POST";
request.cachePolicy = TTURLRequestCachePolicyNoCache;
request.response = [[[TTURLJSONResponse alloc] init] autorelease];
[request.parameters addObject:nombre forKey:#"username"];
[request.parameters addObject:email forKey:#"email"];
[request.parameters addObject:pass1 forKey:#"pass"];
[request.parameters addObject:pass2 forKey:#"cpass"];
I know that i need to use:[request sendSynchronously];to send the data but i don't know how to save the data that i'll retrieve from the server into a variable because this method only gives me a true or false.
The second thing i would like to know is how to set an image loading activity indicator into a uitable to block this while the request is being send to the server and quit that image once it has finished.
Thanks a lot for your help.
Answer #1: You set up a TTURLRequestDelegate and define the methods of what you want to happen for each callback.
Answer #2: This isn't Three20 specific, you should just be able to add the loading image when you make the request, and then remove it once you get one of the above mentioned delegate methods called.
On a side note: make sure that if you're actually doing something synchronously that you do not do it on the UI thread as it will make your app hang.

Loading multiple images in sequence on iPad

I'm working on an application that talks home to a server and retrieves some data with image URL's embedded in it. I want to display those images on the view, and am getting them like so:
UIImageView *ivAvatar = [[UIImageView alloc] initWithImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:self.avatarUrl]]]];
[self.view addSubview:ivAvatar];
[ivAvatar release];
However, whenever data is retrieved (for example, on startup of the application), there is a delay between the retrieval of the data and the user being able to interact with the application due to the blocking nature of dataWithContentsofURL.
What is the proper way to do "Asynchronous" downloading of images? I need the UI to be responsive and load all other data that is retrieved, but load the images while allowing the UI to be responsive.
Any suggestions?
NSURL, NSURLRequest, and NSURLConnection.