2012-04-12 6 views
6

Pobierane są obrazy do mojej aplikacji, które po kilku tygodniach nie będą mieć na uwadze użytkownika. Pobieram je do aplikacji, aby nie musiały być pobierane przy każdym uruchomieniu. Problem polega na tym, że nie chcę, aby folder Dokumenty był większy niż musi. Więc pomyślałem, że mogę "wyczyścić" plik starszy niż miesiąc.iOS - Jak selektywnie usuwać pliki starsze niż miesiąc w Katalogu dokumentów

Problem polega na tym, że będzie kilka plików, które będą starsze niż miesiąc, ale których NIE chcę usuwać. Będą to pliki nazwane statycznie, więc będą łatwe do zidentyfikowania, a będzie ich tylko 3 lub 4. Chociaż może istnieć kilkadziesiąt starych plików, które chcę usunąć. Oto przykład:

picture.jpg   <--Older than a month DELETE 
picture2.jpg   <--NOT older than a month Do Not Delete 
picture3.jpg   <--Older than a month DELETE 
picture4.jpg   <--Older than a month DELETE 
keepAtAllTimes.jpg <--Do not delete no matter how old 
keepAtAllTimes2.jpg <--Do not delete no matter how old 
keepAtAllTimes3.jpg <--Do not delete no matter how old 

W jaki sposób mogę selektywnie usunąć te pliki?

Z góry dziękuję!

+0

Przejrzyj katalog, wyodrębnij daty plików i usuń starsze niż miesiąc. Mieć listę plików do porównania dla tych, których nie chcesz usunąć. –

+0

Tak. to samo pytanie zadano zaledwie 3 dni wcześniej. –

Odpowiedz

12

Kod do usuwania plików starszych niż dwa dni. Oryginalnie odpowiedziałem na here. Testowałem to i działało w moim projekcie.

P.S. Przed usunięciem wszystkich plików w katalogu dokumentów należy zachować ostrożność, ponieważ może to spowodować utratę pliku bazy danych (jeśli używasz .. !!), co może powodować problemy z aplikacją. To dlatego zachowałem, jeśli stan tam. :-))

// Code to delete images older than two days. 
    #define kDOCSFOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] 

NSFileManager* fileManager = [[[NSFileManager alloc] init] autorelease]; 
NSDirectoryEnumerator* en = [fileManager enumeratorAtPath:kDOCSFOLDER];  

NSString* file; 
while (file = [en nextObject]) 
{ 
    NSLog(@"File To Delete : %@",file); 
    NSError *error= nil; 

    NSString *filepath=[NSString stringWithFormat:[kDOCSFOLDER stringByAppendingString:@"/%@"],file]; 


    NSDate *creationDate =[[fileManager attributesOfItemAtPath:filepath error:nil] fileCreationDate]; 
    NSDate *d =[[NSDate date] dateByAddingTimeInterval:-1*24*60*60]; 

    NSDateFormatter *df=[[NSDateFormatter alloc]init];// = [NSDateFormatter initWithDateFormat:@"yyyy-MM-dd"]; 
    [df setDateFormat:@"EEEE d"]; 

    NSString *createdDate = [df stringFromDate:creationDate]; 

    NSString *twoDaysOld = [df stringFromDate:d]; 

    NSLog(@"create Date----->%@, two days before date ----> %@", createdDate, twoDaysOld); 

    // if ([[dictAtt valueForKey:NSFileCreationDate] compare:d] == NSOrderedAscending) 
    if ([creationDate compare:d] == NSOrderedAscending) 

    { 
     if([file isEqualToString:@"RDRProject.sqlite"]) 
     { 

      NSLog(@"Imp Do not delete"); 
     } 

     else 
     { 
      [[NSFileManager defaultManager] removeItemAtPath:[kDOCSFOLDER stringByAppendingPathComponent:file] error:&error]; 
     } 
    } 
} 
+0

Próbowałem tego pierwotnie, ale nie odniosłem sukcesu. Dałem mu kolejne zdjęcie i teraz działa. Dzięki! – Louie

+0

Ahaa .. Fajnie .. Właściwie próbowałem przez kilka minut na to pytanie i zweryfikowałem je w mojej uruchomionej aplikacji to działało, a następnie opublikowałem kod. Zobaczysz dodatkowy kod do weryfikacji daty w moim kodzie .. :-)) –

+0

@ ParthBhatt: Ale ja sam tam odpowiedziałem. Nic nie skopiowałem. –

4

Możesz pobrać datę utworzenia pliku, spójrz na to SO Post, a następnie po prostu porównaj daty. i utworzyć dwie różne tablice dla plików musi zostać usunięty i nie zostać usunięte ..

+0

+1 dla poprawnej odpowiedzi. Jednak zamiast używać rozwiązania w połączonym pytaniu, sugerowałbym użycie 'NSMetadataQuery', który automatycznie wyszuka pliki starsze niż określona data. – Saphrosit

0

Oto funkcja, która nie korzysta z porównania ciągów znaków dla dat i wstępnie wyłapuje czas modyfikacji w wyliczający:

+ (NSArray<NSURL *> *)deleteFilesOlderThan:(NSDate *)earliestDateAllowed 
           inDirectory:(NSURL *)directory { 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSDirectoryEnumerator<NSURL *> *enumerator = 
     [fileManager enumeratorAtURL:directory 
      includingPropertiesForKeys:@[ NSURLContentModificationDateKey ] 
           options:0 
          errorHandler:^BOOL(NSURL *_Nonnull url, NSError *_Nonnull error) { 
           NSLog(@"Failed while enumerating directory '%@' for files to " 
             @"delete: %@ (failed on file '%@')", 
             directory.path, error.localizedDescription, url.path); 
           return YES; 
          }]; 

    NSURL *file; 
    NSError *error; 
    NSMutableArray<NSURL *> *filesDeleted = [NSMutableArray new]; 
    while (file = [enumerator nextObject]) { 
     NSDate *mtime; 
     if (![file getResourceValue:&mtime forKey:NSURLContentModificationDateKey error:&error]) { 
      NSLog(@"Couldn't fetch mtime for file '%@': %@", file.path, error); 
      continue; 
     } 

     if ([earliestDateAllowed earlierDate:mtime] == earliestDateAllowed) { 
      continue; 
     } 

     if (![fileManager removeItemAtURL:file error:&error]) { 
      NSLog(@"Couldn't delete file '%@': %@", file.path, error.localizedDescription); 
      continue; 
     } 
     [filesDeleted addObject:file]; 
    } 
    return filesDeleted; 
} 

Jeśli nie dbają o plikach usunięty, możesz zwrócić go BOOL, aby wskazać, czy wystąpiły jakieś błędy, lub po prostu void, jeśli chcesz zrobić próbę najlepszego wysiłku.

Aby zachować wybiórczo niektóre pliki, dodaj argument wyrażenia regularnego do funkcji, która powinna pasować do przechowywanych plików, i dodaj zaznaczenie w pętli while (najlepiej pasuje do Twojego przypadku użycia) lub istnieje dyskretna liczba plików o różnych wzorach, które można zaakceptować NSSet wraz z nazwami plików, aby zachować i sprawdzić, czy zostały włączone do zestawu przed przystąpieniem do usuwania.

Także wspominając o tym tutaj, ponieważ może to być istotne dla niektórych: System plików na iOS i OSX nie przechowuje mtime z większą precyzją niż sekundę, więc uważaj na to, jeśli potrzebujesz dokładności milisekundy lub podobnej.

Odpowiadający przypadek test spadek do swojego zestawu testowego, jeśli chcesz:

@interface MCLDirectoryUtilsTest : XCTestCase 

@property NSURL *directory; 

@end 


@implementation MCLDirectoryUtilsTest 

- (void)setUp { 
    NSURL *tempdir = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES]; 
    self.directory = [tempdir URLByAppendingPathComponent:[NSUUID UUID].UUIDString isDirectory:YES]; 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    [fileManager createDirectoryAtURL:self.directory 
      withIntermediateDirectories:YES 
          attributes:nil 
           error:nil]; 
} 


- (void)tearDown { 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    [fileManager removeItemAtURL:self.directory error:nil]; 
} 


- (void)testDeleteFilesOlderThan { 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    // Create one old and one new file 
    [fileManager createFileAtPath:[self.directory URLByAppendingPathComponent:@"oldfile"].path 
         contents:[NSData new] 
         attributes:@{ 
          NSFileModificationDate : [[NSDate new] dateByAddingTimeInterval:-120], 
         }]; 
    [fileManager createFileAtPath:[self.directory URLByAppendingPathComponent:@"newfile"].path 
         contents:[NSData new] 
         attributes:nil]; 

    NSArray<NSURL *> *filesDeleted = 
     [MCLUtils deleteFilesOlderThan:[[NSDate new] dateByAddingTimeInterval:-60] 
          inDirectory:self.directory]; 
    XCTAssertEqual(filesDeleted.count, 1); 
    XCTAssertEqualObjects(filesDeleted[0].lastPathComponent, @"oldfile"); 
    NSArray<NSString *> *contentsInDirectory = 
     [fileManager contentsOfDirectoryAtPath:self.directory.path error:nil]; 
    XCTAssertEqual(contentsInDirectory.count, 1); 
    XCTAssertEqualObjects(contentsInDirectory[0], @"newfile"); 
} 
0

w Swift 3 i 4, aby usunąć określony plik w documentsDirectory

do{ 
    try FileManager.default.removeItem(atPath: theFile) 
} catch let theError as Error{ 
    print("file not found \(theError)") 
} 
0

Moje dwa centy warto. Zmiana spełnia Wymagania prawne do dopasowania.

func cleanUp() { 
    let maximumDays = 10.0 
    let minimumDate = Date().addingTimeInterval(-maximumDays*24*60*60) 
    func meetsRequirement(date: Date) -> Bool { return date < minimumDate } 

    func meetsRequirement(name: String) -> Bool { return name.hasPrefix(applicationName) && name.hasSuffix("log") } 

    do { 
     let manager = FileManager.default 
     let documentDirUrl = try manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 
     if manager.changeCurrentDirectoryPath(documentDirUrl.path) { 
      for file in try manager.contentsOfDirectory(atPath: ".") { 
       let creationDate = try manager.attributesOfItem(atPath: file)[FileAttributeKey.creationDate] as! Date 
       if meetsRequirement(name: file) && meetsRequirement(date: creationDate) { 
        try manager.removeItem(atPath: file) 
       } 
      } 
     } 
    } 
    catch { 
     print("Cannot cleanup the old files: \(error)") 
    } 
} 
Powiązane problemy