0

私はFTP アドレスからいくつかのデータをダウンロードするために Nico Kreipke の FTPManager (ここをクリックして GiHub に移動します) を使用しています。

コードは、ユーザーの最初の対話の前に実行された場合に機能しますが、その後は通常失敗します (10 分の 9 程度)。

失敗すると、次のメッセージが書き込まれます (0x_ は実際には有効なアドレスです)。

request (0x_) other than the current request(0x0) signalled it was complete on connection 0x_

そのメッセージは、私のコードでも FTPManager でもなく、Apple によって書かれています。その GitHub で、同じエラーのあるものを見つけましたが、そのソースは私のものと同じである可能性があります。(その人はARCを使っていませんでした。)

コマンドを使用してこれらのアドレスのオブジェクトを出力しようとするとpo、コンソールに説明がないと表示されます。

また、アプリがメモリ警告を受け取るまで、および OS が終了した直後に、メモリが追加され続けます。

そのメッセージが表示されたときにアプリを一時停止すると、メイン スレッドが実行ループになっていることがわかります。

CFRunLoopRun();

コード

self.ftpManager = [[FTPManager alloc] init];
[self downloadFTPFiles:@"192.168.2.1/sda1/1668"];

ftpManagerは強力なリファレンスです。

downloadFTPFiles:メソッド:

- (void) downloadFTPFiles:(NSString*) basePath
{
    NSLog(@"Reading contents of path: %@", basePath);

    FMServer* server = [FMServer serverWithDestination: basePath username:@"test" password:@"test"];

    NSArray* serverData = [self.ftpManager contentsOfServer:server];

    NSLog(@"Number of items: %d", serverData.count);

    for(int i=0; i < serverData.count; i++)
    {
        NSDictionary * sDataI = serverData[i];
        NSString* name = [sDataI objectForKey:(id)kCFFTPResourceName];
        NSNumber* type = [sDataI objectForKey:(id)kCFFTPResourceType];

        if([type intValue] == 4)
        {
            NSLog(@"%@ is Folder", name);
            NSString * nextDestination = [basePath stringByAppendingPathComponent: name];
            [self downloadFTPFiles:nextDestination];
        }
        else
        {
            NSLog(@"%@ is File", name);
            [self.ftpManager downloadFile:name toDirectory:[NSURL fileURLWithPath:NSHomeDirectory()] fromServer:server];
        }
    }
}

私がしたこと

私はいくつかの場所でそのコードを実行しようとしました:

  • アプリデリゲートのapplication:didFinishLaunchingWithOptions:;

  • アプリの起動直後に読み込まれるビュー コントローラの と と、後で表示されるビューviewDidLoadコントローラviewWillAppear:viewDidAppear:

  • ボタン イベントでトリガーされるアクションによって。

データのダウンロードは、デリゲートまたはアプリに読み込まれたビュー コントローラーによって実行されると、常に適切に実行されます (例外あり)。ただし、ユーザーがアプリを最初に操作した後に実行すると、前述のエラーで失敗する可能性が高くなります。

ユーザーの最初の操作の前にロードされたビュー コントローラーの例外は、呼び出しがviewWillAppear:またはviewDidAppear:メソッドのいずれかである場合です。2 回目に呼び出されたとき (たとえば、タブ バー コントローラーのタブ) も、ほとんどの場合、失敗します。

質問

誰かが何が起こっているのか、または私が何か間違っているかどうかを知っていますか? または、代替ソリューションはありますか?

この問題を解決するための助けは歓迎されます。

ありがとう、
ティアゴ

4

1 に答える 1

2

ブロックdownloadFile:toDirectory:fromServer:内でメッセージを送信することになりました。dispatch_asyncダウンロードしたファイルごとに FTPManage も作成しました。

うまくいきましたが、その理由はわかりません。

この答えは、この問題に遭遇した人に任せます。

この手法が機能した理由を誰かが教えてくれる場合は、答えを更新できるように、以下にコメントしてください。

各ファイルをダウンロードする新しい方法は次のとおりです。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    FTPManager *manager = [[FTPManager alloc] init];
    [manager downloadFile:name toDirectory:[NSURL fileURLWithPath:path] fromServer:server];
});

繰り返しますが、これが機能した理由を知っている場合は、お知らせください。

ありがとう。

フルメソッド

- (void) downloadFTPFiles:(NSString*) basePath
{
    NSLog(@"Reading contents of path: %@", basePath);

    FMServer *server = [FMServer serverWithDestination:basePath username:@"test" password:@"test"];

    NSArray *serverData = [self.ftpManager contentsOfServer:server];

    NSLog(@"Number of items: %d", serverData.count);

    for(int i=0; i < serverData.count; i++)
    {
        NSDictionary *sDataI = serverData[i];
        NSString *name = [sDataI objectForKey:(id)kCFFTPResourceName];
        NSNumber *type = [sDataI objectForKey:(id)kCFFTPResourceType];

        if([type intValue] == 4)
        {
            NSLog(@"%@ is Folder", name);
            NSString *nextDestination = [basePath stringByAppendingPathComponent:name];
            [self downloadFTPFiles:nextDestination];
        }
        else
        {
            NSLog(@"%@ is File", name);
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                FTPManager *manager = [[FTPManager alloc] init];
                [manager downloadFile:name toDirectory:[NSURL fileURLWithPath:path] fromServer:server];
            });
        }
    }
}
于 2013-10-14T18:00:09.893 に答える