How to predefine Apple Script constants or variables - macos

Is it possible to predefine constant or variable for an AppleScript in cocoa application?
in other words is the function "addConstantToAppleScript" (used in the following code) definable?
addConstantToAppleScript("myText", "Hello!");
char *src = "display dialog myText";
NSString *scriptSource = [NSString stringWithCString:src];
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:scriptSource];
NSDictionary *scriptError = [[NSDictionary alloc] init];
[appleScript executeAndReturnError:scriptError];
thanks.

If you want to prepend an NSDictionary of key/value pairs to the beginning of an NSString containing AppleScript you could use something like the following function. Personally I would do this as a category on NSString but you have asked for a function.
NSString *addConstantsToAppleScript(NSString *script, NSDictionary *constants) {
NSMutableString *constantsScript = [NSMutableString string];
for(NSString *name in constants) {
[constantsScript appendFormat:#"set %# to \"%#\"\n", name, [constants objectForKey:name]];
}
return [NSString stringWithFormat:#"%#%#", constantsScript, script];
}
This function converts the key/value pairs to AppleScript statements of the form set <key> to "<value>". These statements are then added to the front of the supplied script string. The resulting script string is then returned.
You would use the above function as follows:
// Create a dictionary with two entries:
// myText = Hello\rWorld!
// Foo = Bar
NSDictionary *constants = [[NSDictionary alloc ] initWithObjectsAndKeys:#"Hello\rWorld!", #"myText", #"Bar", #"Foo", nil];
// The AppleScript to have the constants prepended to
NSString *script = #"tell application \"Finder\" to display dialog myText";
// Add the constants to the beginning of the script
NSString *sourceScript = addConstantsToAppleScript(script, constants);
// sourceScript now equals
// set Foo to "Bar"
// set myText to "Hello\rWorld!"
// tell application "Finder" to display dialog myText
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:sourceScript];

Related

Multiplying double variable by double in Xcode

I'm making in app that includes a user entering the price of an object, and the app outputs the price including tax. However, every time it outputs 0, and I get a run-time error involving the variable, myDouble. I'm trying to take the value put in a text field and multiplying it by 1.06 (I'm starting out with a set tax rate), and then setting a label to the new value. Here is my code:
-(IBAction)textFieldReturn:(id)sender
{
[sender resignFirstResponder];
NSString *myString = inputtext2.text;
double myDouble = [myString doubleValue];
myDouble = myDouble*1.06;
NSLog(#"myDouble: %lf", myDouble);
price.text = [NSString stringWithFormat:#"%g", myDouble];
}
Most likely your inputtext2 variable is nil, so it is returning nothing. If this is an outlet, check the connections in interface builder. If the outlet is not connected, the variable will be nil, so the string value will be nil, so the double value will be 0.
I think you are going to want to use a NSNumberFormatter and check for valid entry.
pseudo code, uncompiled:
-(IBAction)textFieldReturn:(id)sender
{
[sender resignFirstResponder];
NSString *myString = inputtext2.text;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle: NSNumberFormatterDecimalStyle];
NSNumber *myNumber = [formatter numberFromString: myString];
double myDouble = 0;
if (myNumber != nil) {
myDouble = [myNumber doubleValue];
}
NSString *outputString = [formatter stringFromNumber:myDouble];
price.text = outputString;
}
This should default your number to 0 if the text entered is 0 or not a valid number.

Sort by Double Value and not String Value

I'm currently pulling info from an sql DB where the 'cachedDist' column is set as a double. However when I pull it into my app and create my array I turn it into an String and the sort will obviously be off, 18.15 will come before 2.15. How do I fix that in my code so it will sort distance as a Double and not a String?
In Bar object.
NSString *cachedDist
#property(nonatomic,copy) NSString *cachedDist;
#synthesize cachedDist;
My while loop in the View Controller.
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
Bar * bar = [[Bar alloc] init];
bar.barName = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
bar.barAddress = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
bar.barCity = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
bar.barState = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 4)];
bar.barZip = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 5)];
bar.barLat = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 8)];
bar.barLong = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 9)];
if (currentLoc == nil) {
NSLog(#"current location is nil %#", currentLoc);
}else{
CLLocation *barLocation = [[CLLocation alloc] initWithLatitude:[bar.barLat doubleValue] longitude:[bar.barLong doubleValue]];
bar.cachedDist = [NSNumber numberWithDouble:[currentLoc distanceFromLocation: barLocation]/1000];
[thebars addObject:bar];
}
My sorting
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"cachedDist" ascending:YES];
sortedArray = [thebars sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
return sortedArray;
NSString has a method doubleValue to make this quite simple:
double cachedDistance = [cachedDistanceString doubleValue];
which you can use in a custom comparator for your sorting, or else make the property an NSNumber or double to make sorting that much easier. (I'm not sure how you are sorting...)
edit:
I re-evaluated your code, and now it looks like we are going from a double to a string to a double... we can cut out the middle-man, so to speak.
In your #prototype section, change the #property:
// #property(nonatomic,copy) NSString *cachedDist; // old way
#property(nonatomic) double cachedDist;
then assign it like this:
bar.cachedDistance = [currentLoc distanceFromLocation: barLocation]/1000;
and remove the lines which create a string from the distance (which is actually just a double).
Alternatively, if you want to be more object oriented, you can (should?) use NSNumber objects:
#property(nonatomic,copy) NSNumber *cachedDist;
...
bar.cachedDistance = [NSNumber numberWithDouble:[currentLoc distanceFromLocation: barLocation]/1000];

stringByReplacingOccurenceOfString fails

I'm trying to make a Mac OS X application that asks the user for a directory. I'm using an NSOpenPanel that gets triggered when the user presses a "Browse" button.
The problem is, [NSOpenPanel filenames] was deprecated, so now I'm using the URLs function. I want to parse out the stuff that's url related to just get a normal file path. So I tried fileName = [fileName stringByReplacingOccurrencesOfString:#"%%20" withString:#" "];, but that gave me an error:
-[NSURL stringByReplacingOccurrencesOfString:withString:]: unrecognized selector sent to instance 0x100521fa0
Here's the entire method:
- (void) browse:(id)sender
{
int i; // Loop counter.
// Create the File Open Dialog class.
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
// Enable the selection of files in the dialog.
[openDlg setCanChooseFiles:NO];
// Enable the selection of directories in the dialog.
[openDlg setCanChooseDirectories:YES];
// Display the dialog. If the OK button was pressed,
// process the files.
if ( [openDlg runModal] == NSOKButton )
{
// Get an array containing the full filenames of all
// files and directories selected.
NSArray* files = [openDlg URLs];
// Loop through all the files and process them.
for( i = 0; i < [files count]; i++ )
{
NSString* fileName = (NSString*)[files objectAtIndex:i];
NSLog(#"%#", fileName);
// Do something with the filename.
fileName = [fileName stringByReplacingOccurrencesOfString:#"%%20" withString:#" "];
NSLog(#"%#", fileName);
NSLog(#"Foo");
[oldJarLocation setStringValue:fileName];
[self preparePopUpButton];
}
}
}
Interestingly enough, "Foo" never gets outputted to that console. It's like the method aborts at the stringByReplacigOccurencesOfString line.
If I remove that one line, the app will run and fill my text box with the string, just in URL form, which I don't want.
Your problem is that the NSArray returned by [NSOpenPanel URLs] contains NSURL objects, not NSString objects. You're doing the following cast:
NSString* fileName = (NSString*)[files objectAtIndex:i];
Since NSArray returns an id, there isn't any compile-time checking to make sure your cast makes sense, but you do get a runtime error when you try to send an NSString selector to what is actually an NSURL.
You could convert the NSURL objects to NSString and use your code mostly as-is, but there's no need for you to handle the URL decoding yourself. NSURL already has a method for retrieving the path portion which also undoes percent-encoding: path.
NSString *filePath = [yourUrl path];
Even if your code was dealing with just a percent-encoded NSString, theres stringByReplacingPercentEscapesUsingEncoding:.

Cocoa - Trim all leading whitespace from NSString

(have searched, but not been able to find a simple solution to this one either here, or in Cocoa docs)
Q. How can I trim all leading whitespace only from an NSString? (i.e. leaving any other whitespace intact.)
Unfortunately, for my purposes, NSString's stringByTrimmingCharactersInSet method works on both leading and trailing.
Mac OS X 10.4 compatibility needed, manual GC.
This creates an NSString category to do what you need. With this, you can call NSString *newString = [mystring stringByTrimmingLeadingWhitespace]; to get a copy minus leading whitespace. (Code is untested, may require some minor debugging.)
#interface NSString (trimLeadingWhitespace)
-(NSString*)stringByTrimmingLeadingWhitespace;
#end
#implementation NSString (trimLeadingWhitespace)
-(NSString*)stringByTrimmingLeadingWhitespace {
NSInteger i = 0;
while ((i < [self length])
&& [[NSCharacterSet whitespaceCharacterSet] characterIsMember:[self characterAtIndex:i]]) {
i++;
}
return [self substringFromIndex:i];
}
#end
This is another solution using Regular Expressions (requires iOS 3.2):
NSRange range = [string rangeOfString:#"^\\s*" options:NSRegularExpressionSearch];
NSString *result = [string stringByReplacingCharactersInRange:range withString:#""];
And if you want to trim the trailing whitespaces only you can use #"\\s*$" instead.
This code is taking blanks.
NSString *trimmedText = [strResult stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"%#",trimmedText);
Here is a very efficient (uses CoreFoundation) way of doing it (Taken from kissxml):
- (NSString *)trimWhitespace {
NSMutableString *mStr = [self mutableCopy];
CFStringTrimWhitespace((CFMutableStringRef)mStr);
NSString *result = [mStr copy];
[mStr release];
return [result autorelease];
}
NSString *myText = #" foo ";
NSString *trimmedText = [myText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSLog(#"old = [%#], trimmed = [%#]", myText, trimmedText);
Here's what I would do, and it doesn't involve categories!
NSString* outputString = inputString;
NSRange range = [inputString rangeOfCharacterFromSet: [NSCharacterSet whitespaceCharacterSet]
options:0];
if (range.location == 0)
outputString = [inputString substringFromIndex: range.location + range.length];
This is much less code.
I didn't really have much time to test this, and I'm not sure if 10.4 contains the UTF8String method for NSString, but here's how I'd do it:
NSString+Trimming.h
#import <Foundation/Foundation.h>
#interface NSString (Trimming)
-(NSString *) stringByTrimmingWhitespaceFromFront;
#end
NSString+Trimming.m
#import "NSString+Trimming.h"
#implementation NSString (Trimming)
-(NSString *) stringByTrimmingWhitespaceFromFront
{
const char *cStringValue = [self UTF8String];
int i;
for (i = 0; cStringValue[i] != '\0' && isspace(cStringValue[i]); i++);
return [self substringFromIndex:i];
}
#end
It may not be the most efficient way of doing this but it should work.
str = [str stringByReplacingOccurrencesOfString:#" " withString:#""];

calling a C function using cocoa

I have a C function with the following method signature.
NSString* md5( NSString *str )
How do I call this function, pass in a string, and save the returned string?
I tried the following, but it did not work:
NSString *temp= [[NSString alloc]initWithString:md5(password)];
thanks for your help
You're making it too hard. The stuff in []'s is effectively smalltalk. What you want is to just call the function in C:
NSString * temp = md5(password);
What is password? Is password a common "char *" pointer? Is the md5 signature you put correct?
If that's the case, you could:
NSString *temp = [[NSString alloc] initWithCString:password encoding:NSASCIIStringEncoding];
If your md5 signature is: char *md5(char *password), and you have you password stored in a NSString, you could:
NSString password = #"mypass";
char buff[128];
NSString *temp = [[NSString alloc] initWithString:password];
[temp getCString:buff maxLength:128 encoding:NSASCIIStringEncoding];
char *md5 = md5(buff);
// then you could do whatever you want with md5 var

Resources