-1

I am developing a zip extractor app i followed the algorithm that CRD explained @Here but i stuck at third step i am unable to rename the unzipped file which is at temporary directorary. here is my code

  NSURL *tempDir = [NSURL fileURLWithPath:destinationPath];
        NSError *error;

        NSURL *tmpDirectory = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:tempDir create:YES error:&error];
        if (error) {
            return ;
        }
        tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];
        NSLog(@"temp dir %@",tmpDirectory);
        NSLog(@"temp path %@",tmpDirectory.path);


        [SSZipArchive unzipFileAtPath:zipFilePath toDestination:tmpDirectory.path];

        NSArray *dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpDirectory.path error:nil];
        NSLog(@"dir file %@",dirFiles);
        for (NSString *string in dirFiles) {

            NSArray *dirDestinationFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:destinationPath error:nil];
            NSLog(@"dir destination file %@",dirDestinationFiles);
            [dirDestinationFiles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                NSFileManager *fm = [NSFileManager defaultManager];
                NSError *error;


                if ([string isEqualToString:obj]) {


                    NSLog(@"Already present");

                    BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path  toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-1",string]] error:&error];

                    if (isMoved) {
                        NSLog(@"Moved");
                    }else{
                        NSLog(@"errorL %@", error);
                        NSLog(@"Not moved");
                    }

                    [fm removeItemAtPath:tmpDirectory.path error:&error];

                    [self moveFileToTrash:zipFilePath];
                    [self openExtractedFolderWithZipPath:zipFilePath toDestinationPath:destinationPath];

                }

            }];


        }

Any Suggestions.. Thanks in Advance !

premkolindala
  • 161
  • 10
  • And what is happening exactly ? Does ` NSLog(@"errorL %@", error);` outputs something? Do you have an error at `tmpDirectory`? – Larme Jul 31 '18 at 13:19
  • @Larme no errors output getting like Cannot make directory /Users/Prem/Downloads: File exists – premkolindala Jul 31 '18 at 13:37
  • The unzip has presumably placed one or more items into your temporary directory, you need to *move* each of those items into the directory `destinationPath`. What your code is doing is attempting to *copy* the temporary directory itself, not its contents. To move each item you must handle name clashes, to do this try the move and if you get an error indicating a name clash modify the destination name however you like and re-try the move, repeating until you succeed or you until reach some limit of tries (determined by you). – CRD Jul 31 '18 at 13:54
  • @CRD code edited as you can see i can make one more instance ( BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-1",string]] error:&error]; )this hardcoded how can i make multiple dynamically. – premkolindala Jul 31 '18 at 14:15

2 Answers2

1

Let's just review your code to hopefully help you on your way.

It may seem minor, but pick good variable names:

NSURL *tempDir = [NSURL fileURLWithPath:destinationPath];
NSURL *tmpDirectory = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:tempDir create:YES error:&error];

Two names which are semantically similar for different things, that is just confusing. How about, say, destinationURL instead of tempDir?

Next, when constructing/pulling apart/etc. pathnames or URLs you will be better off being consistent. Both NSURL and NSString provide similar methods for these operations, in one place you use them:

tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];

but then restort to direct string manipulation using a path separator which may, or may not, be correct:

[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-1",string]]

The routines provided by NSURL and NSString abstract away from the details of path separators and how to, say, find the extension on the last path component (which you might find useful when renaming to avoid clashes).

Going back to:

tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];

There is no reason for you to do this. The temporary directory is created for you and you should delete it after using it. So there is no need to create a subdirectory extracts within it, and by reassigning to the same variable you've lost the URL you need to delete the temporary directory.

Now something less obvious, in my comment above I wrote:

To move each item you must handle name clashes, to do this try the move and if you get an error indicating a name clash modify the destination name however you like and re-try the move, repeating until you succeed or you until reach some limit of tries (determined by you).

I didn't explain why you should do it this way and you have tackled the problem a different way: for each item you are going to move you check for names clashes before attempting the move by iterating over the names in the destination directory.

If you read Apple's documentation on the file system you will find they often recommend you try an operation and then examine any error returned instead of trying to predict whether an error will occur and avoid it. The reason for this is the file system is dynamic, other processes can be modifying it, so if you try to avoid an error you may still get one. In pseudocode you are better of doing something like:

moveDone = false
attemptCount = 0
while not moveDone and attemptCount < MAX_ATTEMPTS
   move object
   if object exists error
      modify destination URL
      increment attemptCount
   else
      moveDone = true
   end
end
if not moveDone then handle error

Following this outline and using a simple count and the NSString/NSURL path routines will produce you a much simpler and more reliable solution than the one you have now posted as an answer.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
0

Here is the code working for me.

 NSURL *tempDir = [NSURL fileURLWithPath:destinationPath];
        NSError *error;

        NSURL *tmpDirectory = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:tempDir create:YES error:&error];
        if (error) {
            return ;
        }
        tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];
        NSLog(@"temp dir %@",tmpDirectory);
        NSLog(@"temp path %@",tmpDirectory.path);


        [SSZipArchive unzipFileAtPath:zipFilePath toDestination:tmpDirectory.path];

        NSArray *dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpDirectory.path error:nil];
        NSLog(@"dir file %@",dirFiles);
        for (NSString *string in dirFiles) {

            NSArray *dirDestinationFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:destinationPath error:nil];
            NSLog(@"dir destination file %@",dirDestinationFiles);
            NSMutableArray *folderCount = [[NSMutableArray alloc] init];
            NSMutableArray *folderNumCount = [[NSMutableArray alloc] init];

            [dirDestinationFiles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

               if ([obj containsString:string]){
                    [folderNumCount   addObject:obj];
                }
                if ([string isEqualToString:obj]) {


                    [folderCount addObject:string];

                }

            }];


            NSFileManager *fm = [NSFileManager defaultManager];
            NSError *error;

            if (folderCount.count == 0) {
                NSLog(@"First time extract");


                BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path  toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@",string]] error:&error];

                if (isMoved) {
                    NSLog(@"Moved");
                }else{
                    NSLog(@"errorL %@", error);
                    NSLog(@"Not moved");
                }
                [fm removeItemAtPath:tmpDirectory.path error:&error];

                // [self moveFileToTrash:zipFilePath];
                // [self openExtractedFolderWithZipPath:zipFilePath toDestinationPath:destinationPath];

            }else if (folderCount.count > 0){
                NSLog(@"Already present");

                BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path  toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-%lu",string,folderNumCount.count-1]] error:&error];

                if (isMoved) {
                    NSLog(@"Moved");
                }else{
                    NSLog(@"errorL %@", error);
                    NSLog(@"Not moved");
                }
                [fm removeItemAtPath:tmpDirectory.path error:&error];

                //  [self moveFileToTrash:zipFilePath];
                //  [self openExtractedFolderWithZipPath:zipFilePath toDestinationPath:destinationPath];


            }


        }
premkolindala
  • 161
  • 10