Cocoa contents of directory - objective-c

I have a group/folder with a series of text files. I need to get a path for each one so that I can read the contents, but I can't seem to get anything to work.
I've mucked about with [NSBundle pathsForResourcesOfType:#"txt" inDirectory:#"directoryName"] which gave me nothing but nulls or a single string that reads "Contents", [[NSFileManager defaultManager] enumeratorAtPath:#"directoryName"] which I have no idea what to do with once it's created, and [[NSFileManager defaultManager] contentsOfDirectoryAtPath:#"directoryName" error:nil].
I can't figure out what I'm doing wrong, and at this point I'm just grasping at straws. I went through 20 or 30 pages on here, none of which has really helped.
I should note that this is a Cocoa Application, not iOS.

If you want to read files in arbitrary directories, the path enumerator works nicely. A bit old fashioned, but that has its charm, too.
NSString *docPath = #"/tmp";
NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:docPath];
NSString *filename;
while ((filename = [dirEnum nextObject])) {
//Do something with the file name
}
If you want to read from well-known and defined directories in your home directory, then you can use NSSearchPathForDirectoriesInDomains:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex: 0];
This will give you your Documents directory, and when used with the snippet above, list all files in that folder and subfolders.
Notice that we are not really supposed to use our nice, old Unix paths any more, but instead refer URLs.
In that case, you get something like:
NSArray *URLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *docURL = URLs[0];
NSDirectoryEnumerator *URLEnum = [[NSFileManager defaultManager] enumeratorAtURL: docURL includingPropertiesForKeys: nil options: 0 errorHandler: nil];
NSString *filename;
while ((filename = [URLEnum nextObject])) {
// ...
}
Notice that enumeratorAtURL:includingPropertiesForKeys:options:errorHandler: has all sorts of useful parameters, which you can read about in the docs.

Lets just take 1 of your 3:
[[NSFileManager defaultManager] contentsOfDirectoryAtPath:#"directoryName" error:nil]
You should include the error parameter and check what it contains
You need to supply a full path, not just a "directoryName"
As a result you'll get an array containing the file names of the files in the directory
So if you want the full path you can do:
NSString *directoryPath = ...;
NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:...];
for(NSString *fileName in fileNames) {
NSLog(#"%#", [directoryPath stringByAppendingPathComponent:fileName]);
}

The problem was that when adding the folder, I needed to create a reference to the folder as well. Xcode does not default to this option. I had initially chosen to simply create groups, and this does not do the job.

If your group is in your current project you can use:
NSString *path = [[NSBundle mainBundle] pathForResourcesOfType:#"txt" inDirectory:#"directoryName"]
this should work for you, I noticed that you tried something similar, but make sure you're using mainBundle.

Related

move/copy a file to iCloud

I am a beginner using Objective-C. I used the following code to move a file to iCloud but it gives an error that The operation could not be completed. The file exists.
//store the file locally in document folder
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [docPaths objectAtIndex:0];
filePath = [filePath stringByAppendingString:#"/"];
filePath = [filePath stringByAppendingString:fileName];
NSString *writeError = nil;
NSData * fileData = [NSPropertyListSerialization dataFromPropertyList:dataDic format:NSPropertyListXMLFormat_v1_0 errorDescription:&writeError];
if ([fileData writeToFile:filePath atomically:YES]) {
NSLog(#"Server file is stored locally");
}else {
NSLog(#"%#", writeError);
}
// store the file in iCloud folder
NSURL *ubiquitousURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSString *tmpubiquitousURL = ubiquitousURL.absoluteString;
tmpubiquitousURL = [tmpubiquitousURL stringByAppendingString:fileName];
NSURL *ubi2 = [[NSURL alloc] initWithString:tmpubiquitousURL];
[[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:filePathURL destinationURL:ubi2 error:&error];
I used the following to remove the file from iCloud but it gives an error that Cannot disable syncing on an un-synced file.
[[NSFileManager defaultManager] setUbiquitous:NO itemAtURL:filePathURL destinationURL:ubi2 error:&error];
I checked the availability of iCloud in my app delegate and it's available. The file is an XML file (.plist) and I have a local copy stored in NSDocumentDirectory.
Overall, I want to sync that file in iCloud so it will be accessible on all devices using my app. I have been struggling with this for 2 days, so if you could help me to resolve the problem I would appreciate it.
Note: I would rather not to use UIDocument, however, if that is the only option please let me know.
I also have the same problem while using the code
[[NSFileManager defaultManager] setUbiquitous:NO itemAtURL:filePathURL destinationURL:ubi2 error:&error];
you have to change the code like below for this to work correctly
[[[NSFileManager alloc]init]setUbiquitous:YES itemAtURL:filePathURL destinationURL:ubi2 error:nil];
this code is for moving a file to icloud, also you should change the name of the file you are moving. It should not be same.

Writing to temporary directory does not work

I am trying to write a file to a temporary directory. I am doing it like this:
NSString *_location = NSTemporaryDirectory();
NSString *_guid = [[NSCalendarDate calendarDate] descriptionWithCalendarFormat:#"%m%d%Y%H%M%S%F"];
_guid = [_guid stringByAppendingString:#".png"];
NSString *_tempFilePath = [NSString stringWithFormat:#"%#/%#", _location, _guid];
NSData *_temp_data = [imgRep representationUsingType: NSPNGFileType properties: nil];
[_temp_data writeToFile:_tempFilePath atomically: NO];
But it doesn't work for me. It doesn't create the file. What's the problem?
P.S. I have tried to create a directory with a unique name in NSTemporaryDirectory, and then write to a file there, but it didn't work either.
I noticed that it don't creates a file anywhere. Tried to set location to user's documents folder, but its not working.
Path for writing an image is incorrect:
NSString *_tempFilePath = [NSString stringWithFormat:#"%#/%#", _location,_guid];
OR
NSString *_tempFilePath = [location stringByAppendingPathComponent:#"%#",guid];
If you write to a file inside potentially new directories, you have to first create the directory:
[[NSFileManager defaultManager] createDirectoryAtPath:_directoryPath
withIntermediateDirectories:YES
attributes:nil error:nil];
[_myData writeToFile:[_directoryPath stringByAppendingPathComponent:_fileName]
atomically:YES];

When listing `contentsOfDirectoryAtURL`, I want an array of just the directory names, not the whole path. How do I do this?

I'm using contentsOfDirectoryAtURL to get a listing of a particular directory. Is there a simple way to get just the directory names, rather than the full path?
For example, instead of:
file://localhost/var/mobile/Applications/.../Documents/MySavedFiles/1872399DDF
file://localhost/var/mobile/Applications/.../Documents/MySavedFiles/3431109ABE
I want just
1872399DDF
3431109ABE
Thanks.
First convert the NSURLs into NSStrings, and then you can extract the directory name.
Some very useful methods for NSString are lastPathComponent and stringByDeletingPathExtension
NSMutableArray* directoryNames = [NSMutableArray array];
NSArray* fullPaths = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:...];
for (NSURL* url in fullPaths)
{
[directoryNames addObject:[[url absoluteString] lastPathComponent]];
}
NSArray *URLs = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:...];
NSArray *filenames = [URLs valueForKeyPath:#"lastPathComponent"];

How to create folder in /var/mobile/Documents for jailbroken iOS device?

my app need to download file, but I would like to store all those files into a rep in /var/mobile/Documents.
To create this folder I use :
NSString *path;
path = [#"/var/mobile/Documents/" stringByAppendingPathComponent:#"myFolder"];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) //Does directory already exist?
{
if (![[NSFileManager defaultManager] createDirectoryAtPath:path
withIntermediateDirectories:NO
attributes:nil
error:&error])
{
NSLog(#"Create directory error: %#", error);
}
}
But it's don't work, can you tell me why ?
Thank
You shouldn't get the path to the documents folder that way. Use this instead:
NSString *dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
path = [dir stringByAppendingPathComponent:#"myFolder"];
You shouldn't hard code system paths, except perhaps for /dev/null and /dev/random. Apple can change them at any time in a future iOS version.
BTW /var/mobile/Documents/ isn't writable anyway, because if it were it would interfere with other apps that also write there.

can't save plist. path is not writable

I'm saving a lot of informations in a plist. This one is by standart in my mainBundle.
this is my method to load the path and the data from the plist. if the file in the "application support" folder doesn't exist, i'm copying it from the mainBundle to there.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
self.plistPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist",plistName]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: self.plistPath])
{
NSString *pathInBundle = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
self.plist = [NSMutableDictionary dictionaryWithContentsOfFile:pathInBundle];
NSLog(#"plist doesnt exist");
}
else {
self.plist = [NSMutableDictionary dictionaryWithContentsOfFile:self.plistPath];
NSLog(#"plist exist");
}
NSLog(#"plist path: %#",self.plistPath);
if i add the following lines at the end, there's only NO the answer:
if([fileManager isWritableFileAtPath:self.plistPath]) NSLog(#"YES");
else NSLog(#"NO");
after all, i tried to save with [self.plist writeToFile:self.plistPath atomically:YES];, which is also not working.
sorry for answering so late - i had a lot of other stuff to do. back to my problem: i only get the error, when i try to add a new entry to my dictionary (plist). editing is no problem. i think the problem is, how i try to add the entry. my code looks like:
NSMutableDictionary *updateDict = [[self.plist objectForKey:#"comments"]mutableCopy];
NSMutableDictionary *tmpDict = [[[NSMutableDictionary alloc]init]autorelease];
[tmpDict setObject:comment forKey:#"comment"];
[tmpDict setObject:author forKey:#"author"];
[tmpDict setObject:car forKey:#"car"];
[tmpDict setObject:part forKey:#"part"];
[tmpDict setObject:date forKey:#"date"];
[updateDict setObject:tmpDict forKey:[NSNumber numberWithInt:[updateDict count]+1]];
[self.plist setObject:updateDict forKey:#"comments"];
if([self.plist writeToFile:self.plistPath atomically:YES]) {
return YES;
}
else {
return NO;
}
self.plist is my local copy of the file at plistPath. the structure of my plist looks like: https://img.skitch.com/20111026-tcjxp9ha4up8ggtfjy7ucgqcqe.png
hope this helps
Ok, so that's not the Documents directory and iOS doesn't have an Application Support directory created in the sandbox by default, which is why you can't write.
You can either change your method call to look-up the real documents directory:
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Or, after you get the path to the Application Support directory, you must check to see if it exists already and if not, create it.
please go through the previous post which shows the different way to copy the plist from mainBundle. Use [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error]; method instead.
Did you find answer? if not, you need to change this line:
[updateDict setObject:tmpDict forKey:[NSNumber numberWithInt:[updateDict count]+1]];
to
[updateDict setObject:tmpDict forKey:[NSString stringWithFormat:#"%d",[updateDict count]+1]];
Key name is string, not object.