1

NSTask isn't working; I think it has to do with the arguments. Here is my code:

 - (IBAction)downloadFile:(id)sender {

    // allocate our stuff :D
    progressIndication = [[NSProgressIndicator alloc] init];
    NSTask *downloader = [[NSTask alloc] init];

    // set up the downloader task
    [downloader setLaunchPath:@"/usr/bin/curl"];
    [downloader setArguments:[NSArray arrayWithObject:[NSString stringWithFormat:@"-LO %@", downloadURL]]];

    // go to the Desktop!
    system("cd ~/Desktop");

    // start progress indicator
    [progressIndication startAnimation:self];

    // download!
    [downloader launch];

    // stop the progress indicator, everything is done! :D
    [progressIndication stopAnimation:self];



}

Thanks

walri
  • 11
  • 1
  • 1
    Slightly off-topic but it seems rather pointless to download a file by shelling out to curl while many of Cocoa's built-in classes can do that for you. What are you doing with the downloaded file? – arrtchiu Feb 06 '11 at 06:11
  • 1
    On an unrelated note, you do realize that simply allocating a progress indicator and telling it to animate will do absolutely nothing, right? You have to somehow attach it to the rest of your interface (best done through Interface Builder for novices). – Itai Ferber Feb 06 '11 at 06:24
  • By the way, if you think my solution has answered your question, don't forget to mark it as the answer (click the arrow icon on my post)! ;) – Itai Ferber Feb 06 '11 at 15:47

1 Answers1

3

You really don't need to use curl to do this; just use NSData to accomplish the task much more easily:

NSData *data = [NSData dataWithContentsOfURL:downloadURL];
[data writeToFile:[[NSString stringWithFormat:@"~/Desktop/%@", [downloadURL lastPathComponent]] stringByExpandingTildeInPath] atomically:YES];

If you insist you need to use curl for this, you're going to have to fix your code, which doesn't work for several reasons. First and foremost, your arguments are wrong. You should have the following code:

[downloader setArguments:[NSArray arrayWithObjects:@"-L", @"-O", [downloadURL absoluteString], @"-o", [NSString stringWithFormat:@"~/Desktop/%@", [downloadURL lastPathComponent]], nil];

Second, system("cd ~/Desktop") is meaningless; get rid of it.
Lastly, NSTask runs concurrently. [downloader launch] starts the operation, and your code continues. It should be:

[downloader launch];
[downloader waitUntilExit]; // block until download completes
[progressIndication stopAnimation:self];
Itai Ferber
  • 28,308
  • 5
  • 77
  • 83
  • 1
    +1, but: First, `system("cd ~/Desktop")` will change the current directory that `curl` inherits. It's a bad way to do it, but it achieves the goal of `curl` saving the file to the Desktop instead of the root of the startup disk. A better way is sending the task a `setCurrentDirectoryPath:` message. Second, that NSData solution will necessarily block; NSTask at least provides the opportunity to make it asynchronous. A better solution is NSURLDownload. http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSURLDownload_Class/ – Peter Hosey Feb 06 '11 at 20:05
  • 1
    @Peter Hosey I remember working on a linux box some years ago, thinking that I could `system` commands like that to affect the running process' environment, but it was local to the shell launched by `system` itself. – Richard Mar 06 '11 at 16:34
  • @Richard Oh yes, very good point. `cd ~/Desktop` will only change the shell's working directory, so as Itai says, it's meaningless when given to `system`. – Peter Hosey Mar 06 '11 at 21:25
  • That's what I thought too, but Peter made me second guess myself, so I didn't bother to check. Nice to know that I wasn't too far off... ;) – Itai Ferber Mar 07 '11 at 00:37