Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > Download Progress

Download Progress
Thread Tools
Junior Member
Join Date: Jul 2002
Location: Australia
Status: Offline
Reply With Quote
Aug 27, 2002, 06:52 PM
 
Hi I'd like to make a very simple downloading program. Here is what I have and I want my progress bar to indicate where how much of the file the program has downloaded.

Anway here is my code:

code:
Code:
/* Controller.h */ #import @interface Controller : NSObject { IBOutlet id downloadProgress; NSURL *myURL; NSData *urlContents; } - (IBAction)downloadid)sender; - (void)Bam; @end

code:
[code]
/* Controller.m */

#import "Controller.h"

@implementation Controller

- (IBAction)download(id)sender
{
myURL = [NSURL URLWithString:@"http://www.apple.com/"];
urlContents = [myURL resourceDataUsingCache:YES];

[downloadProgress setUsesThreadedAnimation:YES];

[NSThread detachNewThreadSelector: @selector(Bam) toTarget: self withObject:downloadProgress];

}

- (void)Bam
{
NSAutoreleasePool *apool=[[NSAutoreleasePool alloc] init];

NS_DURING

[urlContents writeToFile:[@"~/Documents/applewebsite.html" stringByExpandingTildeInPath] atomically:YES];
[downloadProgress displayIfNeeded];

NS_HANDLER
NS_ENDHANDLER

[apool release];
}
@end
[/code[
     
Mac Enthusiast
Join Date: Nov 2001
Status: Offline
Reply With Quote
Aug 28, 2002, 01:52 AM
 
OK, first of all, a few things. You've sent the controller a Bam message, passing downloadProgress as the argument. Firstly, methods (like Bam) should start with a lowercase letter and a method executed in a thread should take one argument, which Bam doesn't take—you don't need to pass downloadProgress as the object to the NSThread; pass nil instead. The only reason downloadProgress works is that it's an ivar; on a side note, it's best to statically type outlets in IB. So, your ivar declaration should begin with:
IBOutlet NSProgressIndicator *downloadProgress;

There's absoutely no reason why

[urlContents writeToFile:[@"~/Documents/applewebsite.html" stringByExpandingTildeInPath] atomically:YES];
[downloadProgress displayIfNeeded];

needs to be in an NS_HANDLER block. NS_DURING, NS_HANDLER and NS_ENDHANDLER are designed to catch exceptions. However, neither writeToFile:atomically: nor displayIfNeeded raise any exceptions. So you can remove that. Also, why are calling displayIfNeeded? It forces the progress indicator to redraw if it's been marked as needing display. You don't need to do this.

Actually, after reading through your code, there's no need to either (a) set your progress indicator to use threaded animation, or (b) do what you're doing in a separate thread.

Because you want to find out the status of the download, you'll have to use NSURLHandle.

Here's what each file should contain:

Controller.h
Code:
#import <Cocoa/Cocoa.h> @interface Controller : NSObject <NSURLHandleClient> { IBOutlet NSProgressIndicator *downloadProgress; } - (IBAction)download:(id)sender; @end
Controller.m
Code:
- (IBAction)download:(id)sender { NSURLHandle *handle; NSURL *url; url = [NSURL URLWithString:@"http://www.apple.com"]; handle = [NSURLHandle cachedHandleForURL:url]; [handle addClient:self]; [handle beginLoadInBackground]; } - (void)URLHandleResourceDidBeginLoading:(NSURLHandle *)sender { [downloadProgress startAnimation:nil]; } - (void)URLHandle:(NSURLHandle *)sender resourceDataDidBecomeAvailable:(NSData *)newBytes { if (!totalBytesToRetrieve) { id contentLength; double totalBytesToRetrieve; contentLength = [sender propertyForKeyIfAvailable:@"Content-Length"]; totalBytesToRetrieve = [contentLength doubleValue]; [downloadProgress setIndeterminate:NO]; [downloadProgress setDoubleValue:0.0]; [downloadProgress setMaxValue:totalBytesToRetrieve]; } else { double existingBytesRetrieved; double bytesRetrievedSoFar; existingBytesRetrieved = [downloadProgress doubleValue]; bytesRetrievedSoFar = existingBytesRetrieved + [newBytes length]; [downloadProgress setDoubleValue:bytesRetrievedSoFar]; } } - (void)URLHandleResourceDidFinishLoading:(NSURLHandle *)sender { NSData *fileData; NSString *saveFile; fileData = [sender resourceData]; saveFile = [@"~/Documents/Apple Website.html" stringByExpandingTildeInPath]; [fileData writeToFile:saveFile atomically:YES]; } - (void)URLHandleResourceDidCancelLoading:(NSURLHandle *)sender { [downloadProgress setIndeterminate:YES]; [downloadProgress stopAnimation:nil]; } - (void)URLHandle:(NSURLHandle *)sender resourceDidFailLoadingWithReason:(NSString *)reason { [downloadProgress setIndeterminate:YES]; [downloadProgress stopAnimation:nil]; NSLog(@"Oops! Here's what went wrong: %@", reason); }
It's untested, but it should work.
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 06:13 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2