5
votes

I'm porting my application from XCode7 and iOS 9.x to XCode8 and iOS10. I'm struggling with the handling of the files.

I need to download a file from my backend and after that to move it from /Documents to /tmp. Here is my code:

    AFURLSessionManager *manager = ...

    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
        NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
        return [documentsDirectoryPath URLByAppendingPathComponent:[response suggestedFilename]];
    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
        if(error) {
            ...
        } else {

            NSFileManager *fileManager = [NSFileManager defaultManager];

            NSError *error;
            NSString *tmpDirectory = NSTemporaryDirectory();
            NSString *tmpPDFPath = [tmpDirectory stringByAppendingPathComponent:[[response suggestedFilename] stringByReplacingOccurrencesOfString:@" " withString:@""]];

            if ([fileManager fileExistsAtPath:tmpPDFPath] == YES) {
                [fileManager removeItemAtPath:tmpPDFPath error:&error];
            }

            NSLog(@"readable %d", [fileManager isReadableFileAtPath:filePath]);
            // Print TRUE
            NSLog(@"tmpWritable %d", [fileManager isWritableFileAtPath:[NSURL URLWithString:tmpDirectory]]);
            // Print TRUE

            BOOL move = [fileManager moveItemAtPath:filePath toPath:tmpPDFPath error:&error];

            ...
        }
    }];

Everything works fine if I run my application in an iOS 9.3 simulator, but the app crashes when run in an iOS10 one. The first change I had to made is to pass to the moveItemAtPath method filePath.absoluteString instead of filePath. Despite this editing, the move method always fails with this error:

Error Domain=NSCocoaErrorDomain Code=4 "“XXXX.pdf” couldn’t be moved to “tmp” because either the former doesn't exist, or the folder containing the latter doesn't exist." UserInfo={NSSourceFilePathErrorKey=/file:/Users/XXX/Library/Developer/CoreSimulator/Devices/24CAB2B2-F495-4CFF-90A7-5C51AF38C194/data/Containers/Data/Application/3D8EEEF9-F639-4D6C-BD5E-17A571F7B836/Documents/XXXX.pdf, NSUserStringVariant=( Move ), NSFilePath=/file:/Users/XXXX/Library/Developer/CoreSimulator/Devices/24CAB2B2-F495-4CFF-90A7-5C51AF38C194/data/Containers/Data/Application/3D8EEEF9-F639-4D6C-BD5E-17A571F7B836/Documents/“XXXX.pdf, NSDestinationFilePath=/Users/“XXXX/Library/Developer/CoreSimulator/Devices/24CAB2B2-F495-4CFF-90A7-5C51AF38C194/data/Containers/Data/Application/3D8EEEF9-F639-4D6C-BD5E-17A571F7B836/tmp/“XXXX.pdf, NSUnderlyingError=0x7b0a3500 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

Has anyone already dealt with that kind of error?

2

2 Answers

5
votes

My first workaround is to pass through the NSData:

 NSError* errorWrite = nil;
 NSData* data = [NSData dataWithContentsOfURL:filePath];
 BOOL write = [data writeToFile:tmpPDFPath options:NSDataWritingAtomic error:&errorWrite];

This code works fine, but I would like to understand why the previous one doesn't.

1
votes

I had the same issue and the solution for me was to update to the latest version of the Dropbox SDK (currently 3.2.0) from 3.0.15. In particular, I was still targeting iOS 8.x so my CocoaPods update was not picking up the newer versions of Dropbox and this error was fixed around version 3.0.18. See this forum QA for more details.