saving data as a file in mac osx - objective-c

Basically, i want to save NSData as a file using NSSaver. what do i add into my if statement to save it/what corrections should i make to this method?
- (IBAction)saveAs:(id)sender{
NSMutableArray *storage = [NSMutableArray arrayWithCapacity:[[arrayController arrangedObjects] count]];
for (int i = 0; i < [[arrayController arrangedObjects] count]; i++) {
Stores *object = [[arrayController arrangedObjects] objectAtIndex:i];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:object.Website, #"website",object.Street_Address, #"streetAddress", object.City_Address, #"cityAddress", object.Name, #"storeName", object.Latitude, #"latidude", object.Longitude, #"longitude", object.Phone_Number, #"phoneNumber", nil];
[storage addObject:dict];
}
NSData *data = [NSKeyedArchiver archiveDataWithRootObject:storage];
NSSavePanel *saver = [NSSavePanel savePanel];
saver.requiredFileType = #"yogurtstorelocations";
[saver runModal];
if ([saver runModal] == NSOKButton){
}
}

Error handling code omitted.
[data writeToURL:[saver URL] atomically:YES];

Related

run applescript from cocoa app stopped working

This code had been working fine until just recently. I hadn't' changed anything nor upgraded my system and I'm completely flummoxed.
I've been using it for 6 years and now it dies on me.
Is there an easier or better way of running an applescript from within a cocoa application? At this point I'm happy to pay to fix this problem!
utils.h
#import <Foundation/Foundation.h>
#interface Utils : NSObject
// Runs an applescript with a given map of variables (name/value)
+ (NSArray *)runApplescript:(NSString *)source withVariables:(NSDictionary *)variables;
// Runs an applescript from a file pathwith a given map of variables
// (name/value)
+ (NSArray *)runApplescriptFromFile:(NSString *)scriptName withVariables:(NSDictionary *)variables;
+ (NSArray *)arrayFromDescriptor:(NSAppleEventDescriptor *)descriptor;
// String is empty or only has white characters (space, tab...)
+ (BOOL)stringIsEmptyOrWhite:(NSString *)string;
#end
Utils.M
#import "Utils.h"
#implementation Utils
+ (NSArray *)arrayFromDescriptor:(NSAppleEventDescriptor *)descriptor {
// Enumerate the apple descriptors (lists) returned by the applescript and
// make them into arrays
NSMutableArray *returnArray = [NSMutableArray array];
NSInteger counter, count = [descriptor numberOfItems];
for (counter = 1; counter <= count; counter++) {
NSAppleEventDescriptor *desc = [descriptor descriptorAtIndex:counter];
if (nil != [desc descriptorAtIndex:1]) {
[returnArray addObject:[Utils arrayFromDescriptor:desc]];
} else {
NSString *stringValue = [[descriptor descriptorAtIndex:counter] stringValue];
if (nil != stringValue) {
[returnArray addObject:stringValue];
} else {
[returnArray addObject:#""];
}
}
}
return returnArray;
}
+ (NSString *)escapeCharacters:(NSString *)string {
return [string stringByReplacingOccurrencesOfString:#"\"" withString:#"\\\""];
}
+ (NSArray *)runApplescript:(NSString *)source withVariables:(NSDictionary *)variables {
NSString *input = #"";
NSArray *variableNames = [variables allKeys];
// Transform the dictionary of names/values to set sentences of applescript
for (NSString *variableName in variableNames) {
NSObject *variableValue = [variables objectForKey:variableName];
if ([variableValue isKindOfClass:[NSString class]]) {
input =
[input stringByAppendingString:[NSString stringWithFormat:#"set %# to (\"%#\" as text)\n", variableName,
[Utils escapeCharacters:variableValue], nil]];
} else if ([variableValue isKindOfClass:[NSNumber class]]) {
input = [input stringByAppendingString:[NSString stringWithFormat:#"set %# to (%# as integer)\n",
variableName, variableValue, nil]];
} else if ([variableValue isKindOfClass:[NSArray class]]) {
// Initialize a list
NSString *entry;
NSArray *values = (NSArray *)variableValue;
input = [input stringByAppendingString:[NSString stringWithFormat:#"set %# to {", variableName]];
BOOL first = TRUE;
for (entry in values) {
if (!first) {
input = [input stringByAppendingString:#", "];
}
input = [input
stringByAppendingString:[NSString stringWithFormat:#"\"%#\"", [Utils escapeCharacters:entry], nil]];
first = FALSE;
}
input = [input stringByAppendingString:#"}\n"];
}
}
NSString *finalScript = [input stringByAppendingString:[NSString stringWithFormat:#"\n\n%#", source]];
NSLog(#"Final script: %#", finalScript);
NSAppleScript *script = [[NSAppleScript alloc] initWithSource:finalScript];
NSDictionary *error;
NSAppleEventDescriptor *descriptor = [script executeAndReturnError:&error];
NSLog(#"applescript error: %#", [error description]);
// Transform the return value of applescript to nested nsarrays
return [Utils arrayFromDescriptor:descriptor];
}
+ (NSArray *)runApplescriptFromFile:(NSString *)scriptName withVariables:(NSDictionary *)variables {
NSString *scriptPath = [[NSBundle mainBundle] pathForResource:scriptName ofType:#"applescript"];
NSString *scriptSource =
[[NSString alloc] initWithContentsOfFile:scriptPath encoding:NSASCIIStringEncoding error:nil];
return [Utils runApplescript:scriptSource withVariables:variables];
}
+ (BOOL)stringIsEmptyOrWhite:(NSString *)string {
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
return [string isEqualToString:#""];
}
#end
Easier, yes, although whether that’s your actual problem is another question.
http://appscript.sourceforge.net/asoc.html
I assume you’ve already got other details, including sandboxing and hardening settings and plist entries, taken care of. (Recent Xcode upgrades also had a habit of breaking it when auto-upgrading your project files, by turning on hardening for you so Apple events can’t get out.)

How can I search any volume in macOS?

- (void)readFolder:(NSString *)str :(NSMutableDictionary *)dict {
NSArray *appFolderContents = [[NSArray alloc] init];
appFolderContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:str error:nil];
for (NSString *app in appFolderContents) {
if ([app containsString:#".app"])
{
NSString *appName = [[app lastPathComponent] stringByDeletingPathExtension];
NSString *appPath = [NSString stringWithFormat:#"%#/%#", str, app];
NSString *appBundle = [[NSBundle bundleWithPath:appPath] bundleIdentifier];
// NSLog(#"%# -- %#", appPath, appBundle);
NSArray *jumboTron = [NSArray arrayWithObjects:appName, appPath, appBundle, nil];
[dict setObject:jumboTron forKey:appName];
}
}
}
//This searches for apps
- (void)getAPPList {
NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
[self readFolder:#"/Applications" :myDict];
[self readFolder:#"/Applications/Utilities" :myDict];
[self readFolder:#"/System/Library/CoreServices" :myDict];
[self readFolder:#"/Volumes/Macintosh HD/Applications" :myDict ];
// Volumes not named 'Macintosh HD' doesn't work, I'm trying to make it work
[self readFolder:#"/Volumes/*/Applications" :myDict ];
//Some apps are stored in the user's Application folder instead of the main one
[self readFolder:[NSString stringWithFormat:#"%#/Applications", NSHomeDirectory()] :myDict];
//Sometimes people keep apps in Downloads
[self readFolder:[NSString stringWithFormat:#"%#/Downloads", NSHomeDirectory()] :myDict];
//Some apps are stored in the user's Library/Application Support sometimes
[self readFolder:[NSString stringWithFormat:#"%#/Library/Application Support", NSHomeDirectory()] :myDict];
I'm trying to make line 26 ([self readFolder:#"/Volumes/*/Applications" :myDict ]) search all volumes, instead of only searching a volume with a matching/specific name. How can I do this?
I'm using Xcode 9.2
something like this should do the trick (untested)
NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsVolumeKey, nil];
NSArray *volumeUrls = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:keys options:NSVolumeEnumerationSkipHiddenVolumes];
for (NSURL *volumeUrl in volumeUrls)
{
BOOL mayBeBootVolume = NO;
NSString* pathToVolume = [volumeUrl path];
[self readFolder: [pathToVolume stringByAppendingString: #"/Applications"];
}

NSMutableDictionary not saving to local directory

I test to see if a directory is saving and it doesn't seem that it is.
Here is what I have, it's essentially creating a list of which files have been uploaded to Dropbox. DropboxList is declared in the header file and then synchronized.
int i = 0;
DropboxList = [[NSMutableDictionary alloc]init];
do {
[DropboxList setObject:#"NO" forKey:[NSNumber numberWithInt:i]];
i++;
} while (i < sortedFiles.count);
NSLog(#"dropbox list is %#", DropboxList);
NSArray *dropBoxPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dropBoxDocumentsDirectory = [dropBoxPaths objectAtIndex:0];
NSString *dropBoxDataPath = [dropBoxDocumentsDirectory stringByAppendingPathComponent:#"/DropboxUploads"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dropBoxDataPath]) {
[[NSFileManager defaultManager] createDirectoryAtPath:dropBoxDataPath withIntermediateDirectories:NO attributes:nil error:nil];
}
NSString *filePath = [dropBoxDataPath stringByAppendingPathComponent:#"dropboxList.out"];
[DropboxList writeToFile:filePath atomically:YES];
NSMutableDictionary *newDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
NSLog(#"newDictionary list is %#", newDictionary);
Here is my console:
dropbox list is {
0 = NO;
3 = NO;
2 = NO;
1 = NO;
4 = NO;
}
newDictionary list is (null)
I've tried alloc init for the newDictionary before writing and I get the same result. Any ideas?
The problem is with the following line
[DropboxList setObject:#"NO" forKey:[NSNumber numberWithInt:i]];
DropboxList writeToFile only works with the valid property list. For a NSMutableDictionary to be a valid property list object, its keys should be string type instead of NSNumber.
Solution
[DropboxList setObject:#"NO" forKey:[NSString stringWithFormat:#"%d",i]]];
Also, make use of the writeToFile return parameter to validate.
BOOL isWritten = [DropboxList writeToFile:filePath atomically:YES];
if (isWritten)
{
NSMutableDictionary *newDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
NSLog(#"newDictionary list is %#", newDictionary);
{
else
{
NSLog(#"Something went wrong");
}
Okay, so my problem was that I had NSNumbers as the keys, which doesn't work. I made the keys strings, and we're golden.

contentsOfDirectoryAtPath with Contents of Subfolders objective-c

How can I get the contents of a directory and all of its subfolders? I would like to have tree stored in a NSDictionary.
I want the dictionary to print something like this:
{
MyFolder = (
"Water.png",
{
MySubfolder = (
"Note.txt",
{
Sub-Subfolder = (
"3D.pdf",
"MyFile.txt"
);
}
);
}
);
}
Ive tried:
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *array = [manager contentsOfDirectoryAtPath:path error:nil];
NSMutableDictionary *files = [[NSMutableDictionary alloc]init];
NSString *newPath = #"";
for (int i=0; array.count>i; i++) {
newPath = [NSString stringWithFormat:#"%#/%#", path, [array objectAtIndex:i]];
//echo(newPath);
if ([[[manager attributesOfItemAtPath:newPath error:nil] objectForKey:NSFileType] isEqualToString:NSFileTypeRegular])
{
NSLog(#"Setting: %#||%#", [array objectAtIndex:i], [newPath lastPathComponent]);
[files setObject:[array objectAtIndex:i] forKey:[newPath lastPathComponent]];
}
else
{echo([NSString stringWithFormat:#"newPath=%#", newPath]);
dict = [self reachedDirectory:newPath dict:dict oldPath:path];
}
}
NSMutableDictionary *transferred = [dict objectForKey:[newPath lastPathComponent]];
if (!transferred) {
transferred = [[NSMutableDictionary alloc]init];
}
for (int n=0; files.count>n; n++) {
[transferred setObject:[[files allValues] objectAtIndex:n] forKey:[[files allKeys] objectAtIndex:n]];
}
echo([newPath lastPathComponent]);
[dict setObject:transferred forKey:[path lastPathComponent]];
return dict;
But All of the folders are not aligned and it doesnt go past the second dimension of subfolders. I would like it to be able to have as many subfolders that is possible.
Thanks for your help!
You can use NSDirectoryEnumerator class and it provides enumerateAtPath method so that you need to just pass your main folder path and inside that just loop your condtion. So that whatever your subfolder exist it will print the path accordingly.

Add data to plist

I want to create a plist in code and add more "records" from user input to it. I have created a plist, and I can write the user input, but I can't add data to my plist. Every time, it saves the last input and keeps only one "record". This is the code:
-(void) createPlistFile {
manager = [NSFileManager defaultManager];
filepath = #"/Users/agnostos_el/Downloads/PhoneBook/PhoneBook/Epafes.txt";
if ( [manager fileExistsAtPath:filepath] == NO )
{
NSLog(#"Το Αρχειο Δεν Υπαρχει Το δημειουργω");
[[NSFileManager defaultManager]createFileAtPath:filepath contents:nil attributes:nil];
}
}
-(void) openPlistFile {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if( [path count] > 0 ){
pListFile = [[path objectAtIndex:0] stringByAppendingPathComponent:filepath];
NSDictionary *pListDict = [[NSDictionary alloc]initWithContentsOfFile:filepath];
if ( [pListDict count] <= 0 )
{
}
[self createPlistFile];
}
}
- (void) times
{
filepath = #"/Users/agnostos_el/Downloads/PhoneBook/PhoneBook/Epafes.txt";
stoixeia = [NSArray arrayWithObjects:onoma.stringValue, poli.stringValue, odos.stringValue, per.stringValue, tk.stringValue, xora.stringValue,kin.stringValue, kin1.stringValue, kin2.stringValue, kat.stringValue, erg.stringValue, fax.stringValue, email.stringValue, email1.stringValue, email2.stringValue, pros.stringValue, sim.stringValue, nil];
eponimos = epitheto.stringValue;
NSMutableDictionary *atomo = [NSMutableDictionary dictionary];
innerDict = [NSDictionary dictionaryWithObjects:
[NSArray arrayWithObjects: eponimos, stoixeia, nil]
forKeys:[NSArray arrayWithObjects:#"eponimo", #"stoixeia", nil]];
[atomo setObject:innerDict forKey:eponimos];
id plist = [NSPropertyListSerialization dataFromPropertyList:(id)atomo
format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];
record = [[NSData alloc]initWithData:plist];
[record writeToFile:filepath atomically:YES];
}
- (void) eggrafi
{
[self openPlistFile];
[self times];
}
Any suggestions? Thanks.
You are not passing the file contents to createFileAtPath:contents:attributes::
[[NSFileManager defaultManager]createFileAtPath:filepath contents:nil attributes:nil];