22

I'm using this piece of code to try to retrieve the last modified date of a file:

NSError *error = nil;
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath: myFilePath error:&error];

        if (attributes != nil) {
            NSDate *date = (NSDate*)[attributes objectForKey: NSFileModificationDate];
            NSLog(@"Date modiifed: %@", [date description]);
        }
        else {
            NSLog(@"Not found");
        }

This works well for files in the main bundle but not if the file is located in a subdirectory of the app's document folder, with myFilePath like this:

/Users/User/Library/Application Support/iPhone Simulator/6.0/Applications/The App ID Number/Documents/mySubdirectory/My Saved File

It keeps returning "not found".

I know the file is there, as I can view it with finder. I also tried removing the spaces in the file name but this had no effect.

The error log says no such file or directory, so it looks like something must've gone wrong when I tried to copy the file to the document directory.

Weird thing is, iterating through the document sub directory with contentsOfDirectoryAtPath shows the file as being present.

I've tried hard-coding the path and retrieving it programmatically, with:

*myFolder = [documentsDirectory stringByAppendingPathComponent:@"myFolder"];
*myFilePath = [myFolder stringByAppendingPathComponent:theFileName];

Can anyone see where I'm going wrong?

Dima Deplov
  • 3,688
  • 7
  • 45
  • 77
Robert
  • 5,278
  • 43
  • 65
  • 115
  • 1
    What are those three dots in the filename? – trojanfoe Nov 21 '12 at 16:36
  • Apologies; They represent the rest of the path, which I removed for brevity: `/6.0/Applications/The App ID Number/` . I've edited the question and re-inserted them. – Robert Nov 21 '12 at 16:38
  • Is the file in your xcode project? created programmatically? – Tin Can Nov 21 '12 at 16:45
  • @Tin Can: It was. I then deleted it from the folder and added a different file manually to see if that would make a difference. – Robert Nov 21 '12 at 16:47
  • Pass an `NSError` to `attributesOfItemAtPath` and see what that says. – trojanfoe Nov 21 '12 at 16:49
  • @trojanfoe: it says no such file or directory, so it looks like something must've gone wrong when I tried to copy the file to the document directory. Weird thing is, iterating through the document sub directory with `contentsOfDirectoryAtPath` shows the file as being present. – Robert Nov 21 '12 at 17:03
  • 1
    @Robert Sherlock Holmes: "When you have eliminated the impossible , whatever remains, however improbable, must be the truth." You say you can see the file in the Finder, so double-check your file path. Seems to be nothing wrong with your code otherwise. – Extra Savoir-Faire Nov 21 '12 at 17:05
  • @trudyscousin: the path is retrieved programmatically: `*myFolder = [documentsDirectory stringByAppendingPathComponent:@"myFolder"];` then `*myFilePath = [myFolder stringByAppendingPathComponent:theFileName];` – Robert Nov 21 '12 at 17:12
  • @Robert So that path is non-nil? (At the risk of asking a stupid question...) – Extra Savoir-Faire Nov 21 '12 at 17:12

6 Answers6

35

Swift 3 solution:

func fileModificationDate(url: URL) -> Date? {
    do {
        let attr = try FileManager.default.attributesOfItem(atPath: url.path)
        return attr[FileAttributeKey.modificationDate] as? Date
    } catch {
        return nil
    }
}
coldfire
  • 946
  • 10
  • 8
23

Try this. I had same problem and solved with something like next:

NSURL *fileUrl = [NSURL fileURLWithPath:myFilePath];
NSDate *fileDate;
[fileUrl getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:&error];
if (!error)
{
//here you should be able to read valid date from fileDate variable
}

hope it helped ;)

HussoM
  • 1,272
  • 13
  • 7
zvjerka24
  • 1,772
  • 1
  • 21
  • 27
  • thanks for the suggestion, although I'm not sure I understood it correctly. I tried this: `NSURL *fileURL = [NSURL URLWithString:fullPathURLString]; NSDate *fileDate; [fileURL getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:&error]; if (!error) { NSLog(@"file modification date = %@", fileDate); }`, and still got null. – Robert Nov 26 '12 at 11:44
  • Are you sure that file exists? Run application in simulator and check if fullPathURLString really exist on your file system. Probably you made some mistake while creating file path, otherwise I'm not sure what it can be. Also check what is contained in error object, maybe it gives you some hint for solving mystery :) if (!error) { NSLog(@"file modification date = %@", fileDate); } else { NSLog(@"Error: %@", error.localizedDescription); } – zvjerka24 Nov 26 '12 at 12:51
  • 1
    Yes, the files exist, although the file names contain spaces which have been replaced by `%20`. Could that be causing the problem? – Robert Nov 26 '12 at 13:50
  • 1
    Here's the error log: `CFURLCopyResourcePropertyForKey failed because it was passed this URL which has no scheme: /Users/User/Library/Application%20Support/iPhone%20Simulator/6.0/Applications/A008CF0F-9EE1-42B5-921C-598FC8420279/Documents/downloads/Diagrams/8101-8101N%20Harsco%20Week%20.doc` – Robert Nov 26 '12 at 14:06
  • It looks to me that file is corrupted or something. Maybe it is not able to read doc file. Have you tried if it's working with .txt file? – zvjerka24 Nov 26 '12 at 14:59
  • Yes, .txt files produce the same outcome. – Robert Nov 26 '12 at 15:36
  • I have no idea what it could be! – zvjerka24 Nov 27 '12 at 12:47
  • Hey, no problem. Thank you very much for your efforts anyway. – Robert Nov 27 '12 at 12:58
  • No problem and tx. If somehow I find out how to deal with this I'll let you know ;) – zvjerka24 Nov 27 '12 at 14:27
  • 3
    Please don’t accept answers unless they actually solve your problem, otherwise it’s an indication for other users that this is indeed represents a solutions. Where it might not be the case. – Maxim Veksler Mar 09 '14 at 17:20
  • 1
    It's a good answer, however you should check for error using the return value from `[NSURL getResourceValue::]` and not the existence of the `NSError` object. – trojanfoe May 11 '14 at 11:10
  • Make the url like this: NSURL *fileUrl = [NSURL fileURLWithPath:filePath]; – guogangj Mar 17 '15 at 09:50
6

Here is a Swift like solution of @zvjerka24 answer:

func lastModified(path: String) -> NSDate? {
    let fileUrl = NSURL(fileURLWithPath: path)
    var modified: AnyObject?
    do {
        try fileUrl.getResourceValue(&modified, forKey: NSURLContentModificationDateKey)
        return modified as? NSDate
    } catch let error as NSError {
        print("\(#function) Error: \(error)")
        return nil
    }
}
FBente
  • 2,160
  • 23
  • 34
3

If you get the error:

"CFURLCopyResourcePropertyForKey failed because it was passed this URL which has no scheme"

You can try to solve this by appending "file:///" to your NSString file path before converting it to NSURL, it worked in my case.

Tonnie
  • 149
  • 2
  • 8
3

Can also do:

NSURL* file = ...
NSError* error;`
NSDate *creationDate = [[NSFileManager defaultManager] attributesOfItemAtPath:file.path error:&error].fileCreationDate;
Alexandre G
  • 1,655
  • 20
  • 30
1

For any file in macOS system we can easily get modification date by using any of below mentioned options:

Way 1:

  • NSString *path = @"path to file";
  • NSError *err = nil;
  • NSDictionary *dic2 = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&err];
  • NSLog(@"File modification Date:%@", dic2[NSFileModificationDate]);

Way 2:

  • MDItemRef itemRef = MDItemCreate(kCFAllocatorDefault, (__bridge CFStringRef)path);
  • NSArray *attributeNames = (__bridge NSArray *)MDItemCopyAttributeNames(itemRef);
  • NSDictionary *attributes = (__bridge NSDictionary *) MDItemCopyAttributes(itemRef, (__bridge CFArrayRef) attributeNames);

  • CFDateRef modifDate = MDItemCopyAttribute(itemRef, kMDItemContentModificationDate);

  • NSDate* modificationDate = (__bridge NSDate*) modifDate;
  • NSLog(@"Modification Date%@", modificationDate);

You can also print various other attributes provided by MDItem : NSLog(@"All attributes%@", attributes);