загружать файлы в фоновом режиме через ftp на iphone - PullRequest
1 голос
/ 05 февраля 2012

Я пытаюсь установить FTP-соединение в приложении.Я хочу загрузить несколько файлов на FTP-сервер, все файлы в одном каталоге.Поэтому сначала я хочу создать удаленный каталог.

- (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];
}

Этот код не работает при выполнении в фоновом потоке с использованием следующего вызова:

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

Я предполагаю, что(фоновые потоки) runloop не работает?Если я отправляю сообщение в главном потоке, загрузка просто работает нормально:

[self createRemoteDir];

, поскольку runloop основного потока запущен и работает.

, но довольно большие файлы будутзакачанный;поэтому я хочу поместить эту рабочую нагрузку в фоновый поток.но как и где я могу настроить NSRunLoop, чтобы вся загрузка происходила в фоновом потоке?Документация Apple по NSRunLoops (особенно как их запускать без использования таймера / источника ввода, как в этом случае) не помогла мне.

Ответы [ 2 ]

2 голосов
/ 06 февраля 2012

Я нашел / создал решение, которое по крайней мере работает для меня.При использовании вышеуказанного метода ( createRemoteDir ) для меня был применен и работал следующий код:

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
}

Он запускается в фоновом потоке и создает каталог на сервере ftp.Мне это нравится больше, чем в других примерах, когда циклы выполнения запускаются только для предполагаемого небольшого интервала, скажем, 1 секунда.

[NSDate distantFuture]

- это дата в будущем (несколько столетий, согласно документации Apple).Но это хорошо, поскольку «условие прерывания» обрабатывается моим свойством класса createDirectory - или возникновением ошибки при запуске runloop.

Я не могу объяснить, почему это работает безЯ явно присоединяю входной источник к циклу выполнения (NSTimer или NSPort), но я предполагаю, что достаточно, чтобы NSOutputStream был запланирован в цикле выполнения фонового потока (см. createRemoteDir ).

0 голосов
/ 05 февраля 2012

Вы также можете попытаться использовать вызов dispatch_async для выполнения вашего createRemoteDir в фоновом режиме. Его гораздо проще использовать, и вам не придется беспокоиться об управлении дополнительными потоками.

Вот как будет выглядеть код:

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [self createRemoteDir];
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...