rtiago42
rtiago42

Reputation: 572

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

I'm using Nico Kreipke's FTPManager (click here to go to GiHub) to download some data from an FTP address.

The code works if it's run before the user's first interaction, after that it will usually fail (about 9 out of 10).

When it fails, the following message is written (0x_ are actually valid addresses):

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

That message isn't written by neither my code nor by FTPManager, but by Apple's. On its GitHub, I've found some one with the same error, but the source of it could possible be the same as mine. (That person wasn't using ARC.)

If I try to print the objects of those addresses with the pocommand, the console writes that there's no description available.

Also, the memory keeps adding up until the app receives a memory warning, and soon after the OS terminates it.

By pausing the app when that message appears, I can see that the main thread is in a run loop.

CFRunLoopRun();

The Code

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

ftpManageris a strong reference.

The downloadFTPFiles: method:

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

What I've Done

I've tried running that code on several places:

The download of the data is always well performed when executed by the delegate or a view controller loaded with the app (with an exception). But when run after the user's first interaction with the app, it'll most likely fail with the mentioned error.

The exception for view controllers loaded before the user's first interaction is when the call is in either the viewWillAppear: or viewDidAppear: methods. When it's called a second time (for example, a tab of a tab bar controller) it'll also, most likely, fail.

The Question

Does anyone have an idea of what may be happening, or if I'm doing something wrong? Or any alternative solution, maybe?

Any help to solve this problem will be welcomed.

Thanks,
Tiago

Upvotes: 0

Views: 572

Answers (1)

rtiago42
rtiago42

Reputation: 572

I ended up sending the downloadFile:toDirectory:fromServer: message inside a dispatch_async block. I've also created an FTPManage for every file downloaded.

It worked, but I have no idea why.

I'm leaving this answer to whomever crosses with this problem.

If anyone can let me know why this technique worked, please comment bellow so I can update the answer.

Here's the new way I'm downloading each file:

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

Again, If you know why this worked, let me know.

Thanks.

Full Method

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

Upvotes: 2

Related Questions