How to list out Recently Opened documents in iOS? - ios

I have listed out all the documents in NSDocument Directory and im able to get the documents that are recently modified using :
NSMutableArray* filesAndProperties = [NSMutableArray arrayWithCapacity:[filesArray count]];
for(NSString* file in filesArray) {
NSString* filePath = [iMgr.documentsPath stringByAppendingPathComponent:file];
NSDictionary* properties = [[NSFileManager defaultManager]
attributesOfItemAtPath:filePath
error:&error];
NSDate* modDate = [properties objectForKey:NSFileModificationDate];
if(error == nil)
{
[filesAndProperties addObject:[NSDictionary dictionaryWithObjectsAndKeys:
file, #"path",
modDate, #"lastModDate",
nil]];
}
}
by fallowing :
Get directory contents in date modified order
Now how can i list out the documents that have been opened and viewed by the user without any editing or modifications ?

Related

UIDocumentPickerViewController copied files disappear on download to test iPad

I am using UIDocumentPickerViewController to allow the user to select files that will be "attached" and available within the App. The concept is allow the user to send detail via email with the selected file attachments.
As each file is attached, I copy the file from the tmp Inbox (where fileManager puts the imported file) to a directory I create within the App document directory called "fileAttachments".
I list the files in a UITableView and the user can select each entry and preview the content within a QLPreviewController view using the path stored in the file object fileOJ.filePath.
It all works swimmingly well, until a reload of the project down to my test iPad, then all the files seem to disappear. My list of the files is still fine, but there is no file at the path location.
Any help with just what is happenning would be greatly appreciated.
- (IBAction)selectFilesAction:(UIBarButtonItem *)sender {
NSArray *UTIs = [NSArray arrayWithObjects:#"public.data", nil];
[self openFilePicker:UTIs];
}
- (void)openFilePicker:(NSArray *)UTIs {
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:UTIs inMode:UIDocumentPickerModeImport];
documentPicker.delegate = self;
documentPicker.allowsMultipleSelection = FALSE;
documentPicker.popoverPresentationController.barButtonItem = self.selectFilesButton;
[self presentViewController:documentPicker animated:TRUE completion:nil];
}
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray <NSURL *>*)urls {
NSLog(#"picked URLs %#", urls);
// selecting multiple documents is cool, but requires iOS 11
for (NSURL *documentURL in urls) {
//get file details
NSDictionary *attr = [documentURL resourceValuesForKeys:#[NSURLFileSizeKey,NSURLCreationDateKey] error:nil];
NSLog(#"object: %#", attr);
NSNumber *fileSize = [attr valueForKey:NSURLFileSizeKey];
NSDate *dateFileCreated = [attr valueForKey:NSURLCreationDateKey];
NSDateFormatter *storageDateFormat = [[NSDateFormatter alloc] init];
[storageDateFormat setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *createdDateString = [storageDateFormat stringFromDate:dateFileCreated];
MMfile *fileObj = [[MMfile alloc]init];
fileObj.fileName = documentURL.lastPathComponent;
fileObj.meetingID = _meetingID;
fileObj.fileSize = fileSize;
fileObj.fileCreateDate = createdDateString;
//move file to new directory
fileObj.filePath = [self movefile:documentURL.lastPathComponent sourceFilePath:documentURL.path directory:#"fileAttachments"];
//save file details
[self.meetingModel saveFile:fileObj];
//refresh array and reload table
self.fileArray = [self.meetingModel getFiles:self.meetingID];
[self.tableView reloadData];
}
}
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
NSLog(#"cancelled");
}
-(NSString *)movefile:(NSString *)filename sourceFilePath:(NSString *)sourcePath directory:(NSString *)directoryName{
// Move file from tmp Inbox to the destination directory
BOOL isDir;
NSError *error;
NSFileManager *fileManager= [NSFileManager defaultManager];
//get directory path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString* directoryPath;
if (paths>0) {
NSString *documentsDirectory = [paths objectAtIndex:0];
directoryPath = [NSString stringWithFormat:#"%#/%#",documentsDirectory,directoryName];
}
if(![fileManager fileExistsAtPath:directoryPath isDirectory:&isDir])
if(![fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:NO attributes:nil error:NULL])
NSLog(#"Error: Create folder failed %#", directoryPath);
NSString *destinationPath = [NSString stringWithFormat:#"%#/%#",directoryPath,filename];;
BOOL success = [fileManager moveItemAtPath:sourcePath toPath:destinationPath error:&error];
if (success) {
NSLog(#"moved file");
}else{
NSLog(#"error %#",error.description);
}
return destinationPath;
}
Found the issue. When the project is rebuilt and downloaded to the iPad the AppID changes, and as the documents path includes the AppID, so the documents path changes. Key is not to save the file path, only the file name and rebuild the path each instance. After having found the issue, I now see other similar posts I didn't find earlier. Also see Document directory path change when rebuild application

Get file name of copied document off UIPasteBoard

I am trying to add a feature to an existing iOS app so that documents "copied" within Mail (say a PDF) can be pasted into my app.
After a PDF document is viewed in Mail and "Copy" chosen from the Action menu, within my app's code, when I inspect:
[[UIPasteboard generalPasteboard] items]
I can see the document as per:
{
"com.adobe.pdf" = {length = 875113, bytes = 0x25504446 2d312e35 0d0a25b5 b5b5b50d ... 300d0a25 25454f46 };
}
)
And further retrieve it via:
po [[UIPasteboard generalPasteboard] valueForPasteboardType:#"com.adobe.pdf"]
<OS_dispatch_data: data[0x2820e5c00] = { leaf, size = 875113, buf = 0x1125e0000 }>
However, is there any way to get the document's name? In the Files.app when I paste the same document it gets pasted as the original file name.
Should I be using the pasteboard for this, or if there another API which can get access to the copied document with the file name?
Even if this question is a little older I happened to search for the same and finally found the solution. So for future reference:
Starting with iOS 11 UIPasteboard contains an array itemProviders which gives you all the information about the objects that are available. The same is used for Drag/Drop.
So with the following logic you can save the items to a certain path:
NSArray *items = [[UIPasteboard generalPasteboard] itemProviders];
for (NSInteger i = 0; i < itemProvider.count; i++) {
NSItemProvider *itemProvider = itemProvider[i];
NSString *identifier = itemProvider.registeredTypeIdentifiers[0];
[itemProvider loadDataRepresentationForTypeIdentifier:identifier completionHandler:^(NSData * _Nullable data, NSError * _Nullable error) {
NSMutableDictionary *result;
if (!error) {
NSString *ext = (__bridge NSString *)(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(identifier), kUTTagClassFilenameExtension));
if ([ext isEqualToString:#"jpeg"]) {
ext = #"jpg";
}
NSString *mime = (__bridge NSString *)(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(identifier), kUTTagClassMIMEType));
if (!mime) {
mime = #"application/*";
}
NSString *filename = itemProvider.suggestedName;
NSString *path = [folderPath stringByAppendingPathComponent:filename];
[data writeToFile:path options:NSDataWritingAtomic error:&error];
}
}
}

iOS: Archive Path containing a date

I needed my archive path file name to contain a date.
However, now that I have that working... I realized that I can't get my archive path since I won't know the date when the application opens.
Is there anyway to look up an archive path as a wildcard meaning:
item.archive.%# where %# could be anything (such as a date)?
I'm using NSKeyedArchiver. My file saves -- my problem is getting the file once the application is re-opened since I won't know what the date is.
UPDATE:
In my itemArchivePath function:
NSString *filename = [[NSString alloc] initWithFormat:#"items.archive.%#", date];
return [documentDirectory stringByAppendingPathComponent:filename];
Since I have appended a date to the filename, if I go to call itemArchivePath -- it won't have a date because it won't know what the date is. Is there anyway I can get the item path using a wildcard -- there will only be 1 file saved and I know that the beginning of the path will be items.archive.
This code will allow you to get all the URLs of your archive files:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentDirectory = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];
NSError *error;
NSArray *contents = [fileManager contentsOfDirectoryAtURL:documentDirectory
includingPropertiesForKeys:nil
options:NSDirectoryEnumerationSkipsSubdirectoryDescendants | NSDirectoryEnumerationSkipsPackageDescendants | NSDirectoryEnumerationSkipsHiddenFiles
error:&error];
if (contents)
{
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [[(NSURL *)evaluatedObject lastPathComponent] hasPrefix:#"items.archive."];
}];
contents = [contents filteredArrayUsingPredicate:predicate];
NSLog(#"Archive items: %#", contents);
}
else
{
NSLog(#"Failed to get contents:\n%#", error);
}
You could make it more robust by ensuring (in the predicate) that there are files (and not folders) at those URLs, but I'm guessing that might be overkill for your circumstance.
Use NSFileManager to get the paths of all files in your archive folder. Depending on how you archive you'll then have one file name that you can use or a list of files (dates) that you can show to your user.

Looking for a Logic Solution to Build Dynamic Filepath in iOS

I have a file structure which is being built in the following manner.
1) Each user is provided an ID in MySQL database.
2) When user uploads an image from iphone the image is placed in the following directory:
`../images/[USER_ID]/[IMAGE_NUMBER].jpg`
3) In the path noted above, [IMAGE_NUMBER] is generated based upon the submission value. So the first image uploaded will be titled 1.jpg, the second as 2.jpg etc…
So to build a sample directory for the purposes of this question the structure could look something like this:
../images-->
../10/1.jpg
../10/2.jpg
../10/3.jpg
../11/4.jpg
../11/5.jpg
../10/6.jpg
../11/7.jpg
So in this case, User #10 uploaded 3 images, then logged out. Along comes User #11 and she uploads 2 images before logging out. And finally, User #10 logs back in and uploads another image.
Okay now that we have the summary of out the directories are being generated and images are dynamically input, let me get to the ultimate question. I would like to be able to display thumbnails of all the images on a view in the iphone when a user clicks a button that we will call btnRefresh
Here is the method that is associated with btnRefresh:
-(IBAction)btnRefreshTapped
{
[self refreshStream];
}
-(void)refreshStream {
[[API sharedInstance] commandWithParams:[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"stream",#"command",
nil]
onCompletion:^(NSDictionary *json) {
[self showStream:[json objectForKey:#"result"]];
}];
}
As you can see this is referencing the API sharedInstance here is that method:
+(API*)sharedInstance
{
static API *sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
sharedInstance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kAPIHost]];
});
return sharedInstance;
}
and finally we come full circle to the URLWithString value:
-(NSURL*)urlForImageWithId:(NSNumber*)IdPhoto isThumb:(BOOL)isThumb {
int IdValue = [[user objectForKey:#"id"] intValue];
NSString* urlString = [NSString stringWithFormat:#"%#/%#upload/%d/%#%#.jpg",
kAPIHost, kAPIPath, IdValue, IdPhoto, (isThumb)?#"-thumb":#""
];
return [NSURL URLWithString:urlString];
}
So, herein lies my problem. As this is currently being defined I can only see the images of the user that is logged into the app when they click btnRefresh. The other image locations show up as greyed out images due to the broken URLs. So, how can I redefine IdValue to cycle through available folders and pull the associated images for display?
I know this is a complex problem so thank you to putting some brainpower into a solution.
I don't know is it what you asking but you can get all files from the directory via this code:
NSArray *contents = [fileManager contentsOfDirectoryAtURL:YourURL
includingPropertiesForKeys:#[] // <-Add key/s if needed
options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"pathExtension == 'jpg'"];
for (NSURL *fileURL in [contents filteredArrayUsingPredicate:predicate])
{
// Enumerate each .jpg file in directory
}
You can specify images directory and you should be able to find the images and get url to that.
The other way is recursively enumerate files in directory, it's more powerful and it can be amended to your requirement:
NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtURL:YOURURL
includingPropertiesForKeys:#[NSURLNameKey, NSURLIsDirectoryKey] // <-Add more key if needed
options:NSDirectoryEnumerationSkipsHiddenFiles
errorHandler:^BOOL(NSURL *url, NSError *error)
{
NSLog(#"Error %#", error);
}];
NSMutableArray *mutableFileURLs = [NSMutableArray array];
for (NSURL *fileURL in enumerator) {
NSString *filename;
[fileURL getResourceValue:&filename forKey:NSURLNameKey error:nil];
NSNumber *isDirectory;
[fileURL getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil];
if (![isDirectory boolValue]) {
[mutableFileURLs addObject:fileURL];
}
}
Hope one of those will be usefull for you.
Modifying what Greg just answered so that you don't have to iterate the array.
NSArray *paths = [fileManager contentsOfDirectoryAtURL:YourURL
includingPropertiesForKeys:#[]
options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
[NSString stringWithFormat:
#"self ENDSWITH '/filename.jpg'"]];
NSArray *filteredArray = [paths filteredArrayUsingPredicate:predicate];
if ([newarray lastObject]) {
//you have your path here
}
filename.jpg is the IdPhoto.jpg in your code. This code with work because of the type of data you have. I have included "/" in filename.jpg so that there are no issues in detecting 110.jpg vs 10.jpg.

contentsOfDirectoryAtPath returning null (iOS)

I'm having trouble displaying all files in directory. I did make a directory named "saves" in the same folder as all the app files.
I use this code:
NSError *error = nil;
NSArray *imageFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:#"saves" error: &error];
NSLog(#"FILES: %#", imageFiles);
Can anyone help me out, because this code logs "null" - so pretending there isn't anything in the folder, but in the folder I made one directory and two empty files.
NSString *documentDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
Check for files in the test directory:
NSArray *filePaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[documentDirPath stringByAppendingPathComponent:#"test"] error:nil]];
It looks to me like you're trying to save a file in your main bundle. Are you doing this on the simulator or on an actual device? You can't save files in your main bundle on a device.
NSError *error = nil;
NSArray *imageFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:#"saves" error: &error];
Not sure what ypou expect this to do...
NSLog(#"FILES: %#", imageFiles);
try this
NSLog(#"Image file count %d", [imageFiles count]);
for ( int i - 0; i <= [imageFiles count] - 1; i++)
{
NSLog(#"file name : %#", [imageFiles objectAtIndex:i]);
}
code NOT tested but I think you get the idea...

Resources