Use stringWithFormat: as a file path in cocoa - cocoa

I'm having a problem with a cocoa application that takes the value of a text field, and writes it to a file. The file path is made using stringWithFormat: to combine 2 strings. For some reason it will not create the file and the console says nothing. Here is my code:
//Get the values of the text field
NSString *fileName = [fileNameTextField stringValue];
NSString *username = [usernameTextField stringValue];
//Use stringWithFormat: to create the file path
NSString *filePath = [NSString stringWithFormat:#"~/Library/Application Support/Test/%#.txt", fileName];
//Write the username to filePath
[username writeToFile:filePath atomically:YES];
Thanks for any help

The problem is that you have a tilde ~ in the path. ~ is expanded by the shell to the user's home directory, but this doesn't happen automatically in Cocoa. You want to use -[NSString stringByExpandingTildeInPath]. This should work:
NSString *fileName = [fileNameTextField stringValue];
NSString *username = [usernameTextField stringValue];
NSString *fileName = [fileName stringByAppendingPathExtension:#"txt"]; // Append ".txt" to filename
NSString *filePath = [[#"~/Library/Application Support/Test/" stringByExpandingTildeInPath] stringByAppendingPathComponent:fileName]; // Expand '~' to user's home directory, and then append filename
[username writeToFile:filePath atomically:YES];

Adding to mipadi's reply, it's better to use -[NSString stringByStandardizingPath] since it does more - and can clean up more problems - than resolving the tilde.

Related

Path for downloads OSX 10.10.5 and xcode 7.2.1

I made for our internal use a app with a today-extension. There I have access to download all files from our server. But I did not get the right path to save it. I want to save it in the users "downloads" or on the users "desktop".
My code to save the file is:
NSArray *docDirs = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory,NSUserDomainMask, YES);
NSString *doc = [docDirs objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/Page1.pdf", doc];
dispatch_async(dispatch_get_main_queue(), ^{
[urlData writeToFile:filePath atomically:YES];
This saves the file
/Users/itsMe/Library/Containers/com.myCompany.downloadApp.ToDayWidget/Data/Downloads/Page1.pdf
I want to save the file in /users/itsMe/Downloads/Page1.pdf or /users/itsMe/Desktop/Page1.pdf.
How can I do this? I tried without success modifying the path:
NSString *homeDir = NSHomeDirectory();
NSString *homeDir1 = [homeDir stringByDeletingLastPathComponent];
NSString *homeDir2 = [homeDir1 stringByDeletingLastPathComponent];
NSString *homeDir3 = [homeDir2 stringByDeletingLastPathComponent];
NSString *homeDir4 = [homeDir3 stringByDeletingLastPathComponent];
NSString *filePath = [NSString stringWithFormat:#"%#/Page1.pdf", homeDir4];
To access the ~/Downloads folder add the com.apple.security.files.downloads.read-write entitlement by setting File Access > Downloads Folder in the Capabilities > App Sandbox section to Read/Write.
~/Desktop is not accessible outside the sandbox.

Log File to NSString

I am using this to get the log files data:
NSFileHandle *file;
file = [NSFileHandle fileHandleForReadingAtPath:#"~/Library/Application Support/RepoManager/*.log"];
NSData *filedata;
filedata = [file readDataToEndOfFile];
NSString *logC;
logC = [[NSString alloc] initWithData:filedata encoding:NSASCIIStringEncoding];
And than write them using this:
NSString *formatString = #"Log: %#";
return [NSString stringWithFormat:formatString, *logC.stringValue];
But it says logC does not contain a string value
NSString does not define a .stringValue property, and even if it did, *logC.stringValue would have no useful meaning in Objective-C. logC itself is what you want to be using as your format parameter. (It's the string containing the contents of the log file.)

Reading a plist

I'm trying to read ~/Library/Preferences/com.apple.mail.plist (on Snow Leopard) to get the email address and other information to enter into the about dialog. I'm using the following code, which is obviously wrong:
NSBundle* bundle;
bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource:#"~/Library/Preferences/com.apple.mail.plist" ofType:#"plist"];
NSDictionary *plistData = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSString *item = [plistData valueForKeyPath:#"MailAccounts.Item 2.AccountName"];
NSLog(#"Result = %#", item);
Moreover, the value I need to read is MailAcounts -> Item 2 -> AccountName and I am not sure I am doing this correctly (due to the space in the Item 2 key).
I tried reading Apple's developer guide to plist files but no help there.
How can I read a plist and extract the values as an NSString?
Thanks.
The first level is an array, so you need to use "MailAccounts.AccountName" and treat it as NSArray*:
NSString *plistPath = [#"~/Library/Preferences/com.apple.mail.plist" stringByExpandingTildeInPath];
NSDictionary *plistData = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSArray *item = [plistData valueForKeyPath:#"MailAccounts.AccountName"];
NSLog(#"Account: %#", [item objectAtIndex:2]);
Alternatively you can go by keys and pull the array from "MailAccounts" first using valueForKey: (which will yield NSArray*) and then objectAtIndex: to get the dictionary of that particular account (useful if you need more than the name).
Two things:
You don't want or need to use NSBundle to get the path to the file. The file lies outside of the app bundle. So you should just have
NSString *plistPath = #"~/Library/Preferences/com.apple.mail.plist";
You have to expand the tilde in the path to the user directory. NSString has a method for this. Use something like
NSString *plistPath = [#"~/Library/Preferences/com.apple.mail.plist" stringByExpandingTildeInPath];

Problems with UIImagePNGRepresentation

I'm trying to use this line of code
[UIImagePNGRepresentation(image, 1.0) writeToFile:pngPath atomically:YES];
But obviously pngPath is undeclared. So I have to use stringByAppendingPathComponent.
I googled examples of this, and I found this
myPlistPath = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: #"%#.plist", plistName] ];
[myPlistPath retain]
;
The problem is that I don't have a plist file, because I don't need one. How can I solve all these issues and writeToFile the UIImage image?
I don't fully understand your question, but to get the full path where your file should be saved, you could try this:
NSString *file = #"myfile.png";
NSString *directory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
NSString *path = [directory stringByAppendingPathComponent: file];
and then:
[UIImagePNGRepresentation(image) writeToFile:path atomically:YES];

Declare String then open string from Path with Cocoa

I've Declared a string Like so
NSString* fileName = [files objectAtIndex:i];
NSLog(fileName);
NSImage* imageFromBundle = [[NSImage alloc] initWithContentsOfFile:fileName];
and want to use that filename to open a file in a different directory.
I came up with this
NSImage* imageFromBundle2;
imageFromBundle2 = [[NSImage alloc] initWithContentsOfFile:#"/Users/rhaynes/Documents/works4/" filename ];
Any help would be appreciated
I'll assume that your fileName string is actually a file name, like "myImage.png". A lot of the Objective-C docs refer to a file name when they really mean file path - so sometimes it's confusing.
What you want to do is create an NSString that represents the complete path to the file you want to load. For instance, you could say:
NSString * path = [NSString stringWithFormat: #"/Users/rhaynes/Documents/works4/%#", fileName];
That line creates a new NSString using the format string and parameters provided (the %# in the format string indicates that the string value of fileName should be inserted there.) StringWithFormat is a really powerful function, so you should definitely check it out in the docs.
Then you could call initWithContentsOfFile:path, and it should give you the image you want.
NSString* fileName = [files objectAtIndex:i]; NSLog(fileName);
Don't pass non-hard-coded strings as format-string arguments. If they contain format specifiers, you'll get garbage or a crash. (Try this with fileName = #"foo%sbar", for example. Then try it with fileName = #"foo%fbar" for even more fun.)
Your NSLog statement should be:
NSLog(#"%#", fileName);
[I] want to use that filename to open a file in a different directory. I came up with this
NSImage* imageFromBundle2; imageFromBundle2 = [[NSImage alloc] initWithContentsOfFile:#"/Users/rhaynes/Documents/works4/" filename ];
You can only concatenate string literals this way; as you've no doubt seen for yourself, this is a syntax error when one of the strings isn't a literal.
First off, if fileName is actually a pathname, you'll need to use lastPathComponent to get the actual filename. So:
NSString *path = [files objectAtIndex:i];
NSString *filename = [path lastPathComponent];
Then, use stringByAppendingPathComponent: to tack this onto the new superpath.
NSString *desiredFilenamePath = [directoryPath stringByAppendingPathComponent:filename];
Now you have the pathname you wanted to pass to NSImage's initializer.

Resources