iOS-как выборочно удалять файлы старше месяца в каталоге документов

я загружаю изображения в свое приложение, которое через несколько недель пользователю будет все равно. Я загружаю их в приложение, поэтому их не нужно будет загружать при каждом запуске. Проблема в том, что я не хочу, чтобы папка документов становилась больше, чем она должна со временем. Поэтому я подумал, что могу" очистить " файл старше месяца.

проблема в том, что там будет несколько файлов, которые будут старше месяца, но которые я не хочу удалять. Они будут статические файлы так их будет легко идентифицировать, и их будет только 3 или 4. Хотя может быть несколько десятков старых файлов, которые я хочу удалить. Вот пример:

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

Как я могу выборочно удалить эти файлы?

спасибо заранее!

6 ответов


код для удаления файлов, которые старше двух дней. Первоначально я ответил здесь. Я протестировал его, и он работал в моем проекте.

P.S. будьте осторожны, прежде чем удалять все файлы в каталоге документов, потому что это может привести к потере файла базы данных(Если вы используете..!!), которая может вызвать проблемы для вашего приложения. Вот почему я сохранил там условие if. : -))

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

вы можете получить дату создания файла, посмотри на это Так пост а затем просто сравните даты. и создайте два разных массива для файлов, которые должны быть удалены и не должны быть удалены..


мои два цента. Измените meetsRequirement в соответствии.

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

чтобы найти дату создания вашего файла, вы можете обратиться к очень полезному сообщению StackOverflow:

iOS: Как найти дату создания файла?

обратитесь к этому сообщению, это может помочь вам в их удалении. Вы можете просто получить приблизительное представление о том, что нужно сделать для удаления этих данных из каталога документов:

как удалить файлы из каталога документов iPhone, которые старше более двух дни

надеюсь, это поможет вам.


вот функция, которая не использует сравнение строк для дат и предваряет время изменения в перечислителе:

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

если вы не заботитесь о файлах, которые были удалены, вы можете вернуть его BOOL, чтобы указать, существуют ли какие-либо ошибки, или просто void Если вы просто хотите сделать возможность.

чтобы выборочно сохранить некоторые файлы, добавьте аргумент регулярного выражения в функцию, которая должна соответствовать файлам сохраните и добавьте чек для этого в цикле while (кажется, лучше всего подходит для вашего варианта использования), или если есть дискретное количество файлов с разными шаблонами, вы можете принять NSSet С именами файлов, которые нужно сохранить и проверить на включение в набор, прежде чем перейти к удалению.

также просто упоминая об этом здесь, так как это может быть актуально для некоторых: файловая система на iOS и OSX не хранит mtime с большей точностью, чем секунду, поэтому следите за этим, если вам требуется миллисекунды точности или аналогичные.

соответствующий тестовый случай, чтобы попасть в ваш набор тестов, если вы хотите:

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

в Swift 3 и 4, чтобы удалить определенный файл в DocumentsDirectory

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