2012-04-12 5 views
6

Sto scaricando immagini sulla mia app che dopo poche settimane l'utente non si preoccuperà. Li scarico nell'app in modo che non debbano essere scaricati ogni avvio. Il problema è che non voglio che la cartella Documenti diventi più grande di quanto non sia nel tempo. Quindi pensavo di poter "ripulire" il file più vecchio di un mese.iOS - Come eliminare selettivamente i file più vecchi di un mese nella directory di documenti

Il problema è che ci saranno alcuni file lì che saranno più vecchi di un mese ma che NON voglio cancellare. Saranno file con nome statico, quindi saranno facili da identificare e ce ne saranno solo 3 o 4. Mentre ci potrebbero essere alcune decine di vecchi file che voglio eliminare. Ecco un esempio:

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 

Come posso cancellare questi file in modo selettivo?

Grazie in anticipo!

+0

Scorrere attraverso la directory, estrarre le date del file ed eliminare quelle più vecchie di un mese. Avere un elenco di file da confrontare per quelli che non si desidera eliminare. –

+0

Sì. la stessa domanda è stata posta solo 3 giorni prima. –

risposta

12

Codice per eliminare i file che sono più vecchi di due giorni. Originariamente ho risposto here. L'ho provato e funzionava nel mio progetto.

P.S. Sii cauto prima di eliminare tutti i file nella directory dei documenti, perché così facendo potresti finire per perdere il file del database (se stai usando .. !!) lì che potrebbe causare problemi alla tua applicazione. Ecco perché ho tenuto se la condizione lì. :-))

// 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

Inizialmente l'ho provato, ma non ha avuto successo. Ho dato un altro colpo e funziona ora. Grazie! – Louie

+0

Ahaa .. Cool .. In realtà ho provato per pochi minuti quella domanda e l'ho verificata nella mia applicazione in esecuzione ha funzionato quindi ho postato il codice .. Vedrai codice extra per la verifica della data nel mio codice .. :-)) –

+0

@ ParthBhatt: Ma io stesso ho risposto lì. Non ho copiato nulla. –

4

È possibile ottenere la data di creazione del file, guardare questo SO Post e quindi confrontare solo le date. e creare due array differenti per i file è necessario cancellare e non da cancellare ..

+0

+1 per la risposta corretta. Tuttavia, anziché utilizzare la soluzione nella domanda collegata, suggerirei di usare 'NSMetadataQuery', che cercherà automaticamente i file più vecchi di una certa data. – Saphrosit

0

Ecco una funzione che non utilizza confronto tra stringhe per le date e precaricamenti la data di modifica nella enumeratore:

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

Se non si preoccupano i file che hai cancellato potresti farlo restituire BOOL per indicare se ci sono stati errori, o semplicemente void se vuoi solo fare un tentativo best-effort.

Per conservare selettivamente alcuni file, aggiungere un argomento di espressione regolare alla funzione che deve corrispondere ai file da conservare e aggiungere un controllo per quello nel ciclo while (sembra adattarsi meglio al caso d'uso), o se c'è una discreta quantità di file con modelli diversi che è possibile accettare uno NSSet con i nomi file da conservare e controllare l'inclusione nel set prima di procedere all'eliminazione.

Anche solo menzionarlo qui perché potrebbe essere rilevante per alcuni: il file system su iOS e OSX non memorizza mtime con maggiore precisione di un secondo, quindi fai attenzione se hai bisogno di precisione millisecondo o simili.

corrispondente banco di prova per cadere nella vostra suite di test se si desidera:

@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

a Swift 3 e 4, per eliminare un file specifico in documentsDirectory

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

I miei due centesimi vale la pena. Il cambiamento incontra il requisito per adattarsi.

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)") 
    } 
}