upload files in background via ftp on iphone

☆樱花仙子☆ 提交于 2020-01-14 04:43:11

问题


i'm trying to establish an FTP connection within an app. i want to upload several files to a FTP server, all files in one directory. So at first i want to create the remote directory.

- (void) createRemoteDir {

    NSURL *destinationDirURL = [NSURL URLWithString: uploadDir];

    CFWriteStreamRef writeStreamRef = CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) destinationDirURL);
    assert(writeStreamRef != NULL);

    ftpStream = (__bridge_transfer NSOutputStream *) writeStreamRef;
    BOOL success = [ftpStream setProperty: ftpUser forKey: (id)kCFStreamPropertyFTPUserName];
    if (success) {
        NSLog(@"\tsuccessfully set the user name");
    }
    success = [ftpStream setProperty: ftpPass forKey: (id)kCFStreamPropertyFTPPassword];
    if (success) {
        NSLog(@"\tsuccessfully set the password");
    }

    ftpStream.delegate = self;
    [ftpStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    // open stream
    [ftpStream open];
}

This code doesn't work when executed in a background thread using the following call:

[self performSelectorInBackground: @selector(createRemoteDir) withObject: nil];

my guess is that the (background-threads) runloop isn't running? If i send the message inside the main thread the uploading just works fine:

[self createRemoteDir];

as the runloop of the main thread is up and running.

but fairly large files are going to be uploaded; so i want to put that workload in a background thread. but how and where do i set up the NSRunLoop, so that the whole uploading happens in a background thread? Apples documentation on NSRunLoops (especially how to start them without using a timer/input source, as in this case) didn't help me out.


回答1:


I found/created a solution that at least works for me. with the above method (createRemoteDir), the following code applied and worked for me:

NSError *error;

createdDirectory = FALSE;
/* 
 only 'prepares' the stream for upload 
 - doesn't actually upload anything until the runloop of this background thread is run
 */
[self createRemoteDir];

NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];

do {

    if(![currentRunLoop runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]]) {

        // log error if the runloop invocation failed
        error = [[NSError alloc] initWithDomain: @"org.mJae.FTPUploadTrial" 
                                           code: 23 
                                       userInfo: nil];
    }

} while (!createdDirectory && !error);

// close stream, remove from runloop
[ftpStream close];
[ftpStream removeFromRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];

if (error) {
    // handle error
}

It runs in a background thread and creates the directory on the ftp server. I like it more than other examples where runloops are only run for an assumed small interval, say 1second.

[NSDate distantFuture]

is a date in the futur (several centuries, according to Apples documentation). But that's good as the "break-condition" is handled by my class property createdDirectory - or the occurance of an error while starting the runloop.

I can't explain why it works without me explicitly attaching an input source to the runloop (NSTimer or NSPort), but my guess is, it is sufficient that the NSOutputStream is scheduled in the runloop of the background thread (see createRemoteDir).




回答2:


You could also try to use a dispatch_async call to perform your createRemoteDir in the background. It's much simpler to use and you won't have to worry about managing extra threads.

Here's what the code would look like:

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [self createRemoteDir];
});


来源:https://stackoverflow.com/questions/9151068/upload-files-in-background-via-ftp-on-iphone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!