Transferring Variables

Hello,

I’m currently working on a mini-application that has a few screens - and I would like to have a separate .applescript file to handle the interactions on each individual screen. However, a lot of screens require data from the screen that came before it; does anyone know of a way that I can transfer my data between script files?

Thanks,
Girasquid

I haven’t posted this til now because I’m sure some one else with more experience has a better way but since no one has posted that better way yet the only way I can think of is to write those variables to file. there they can be read from file by any script that needs them. There probably is a more direct way. I just don’t know what it is. :frowning:

Yeah…writing them to file has been my best idea too.

I guess I’ll check that out; I haven’t had any other solutions appear.

To that end, I’m working on transferring a property between two scripts. It gets updated/set by one of the scripts.

How do I write a property to file so that I can read it back into a different property variable? Just writing it to file seems to always return “list”.

Hi girasquid,

I made a small sample project that shows how you can call a handler of one of the project’s scripts from an other script (which of course can be used to set variables in this script):

http://rapidshare.com/files/62804359/transferVariables.zip.html

… If someone knows a simpler solution … I was interested … :wink:

D.

Oh, cool - didn’t know you could do that with a window’s associated script.

Thanks for figuring that out! It works great now.

Here’s another semi-related question: how would I save the properties? So that a user can load/reload their information?

Also, an interesting issue has cropped up: I managed to load and set the property values, at which point I open the window that the script is attached to - and they suddenly end up emptied. How can I make sure they persist? It seems to me that the value of the properties is getting reset when the window becomes main.

oops sorry, you’re right - you can call handlers this way but since they are run in a different context it seems to be impossible to access the globals and properties of it’s script :frowning:

Ok - second attempt - this one should work (I hope :wink: ):

It needs a little bit of Objective-C. I subclass NSApplication and give it an NSMutableDictionary (equivalent to AppleScript record) where you can store and retrieve your properties - here’s how to:

1. Add this file to your project:

MYApplicationWithPropsContainer.m

[code]#import <Cocoa/Cocoa.h>

@interface MYApplicationWithPropsContainer : NSApplication {
NSMutableDictionary *container;
}
-(void)setProperty:(id)prop forKey:(NSString *)key;
-(id)propertyForKey:(NSString *)key;

@end

@implementation MYApplicationWithPropsContainer

  • (id) init {
    self = [super init];
    if (self != nil) {
    container = [[NSMutableDictionary alloc] init];
    }
    return self;
    }

  • (void) dealloc {
    [container release];
    [super dealloc];
    }

-(void)setProperty:(id)prop forKey:(NSString *)key{
[container setObject:prop forKey:key];
}

-(id)propertyForKey:(NSString *)key{
return ([container objectForKey:key] );
}
@end[/code]
2. edit ‘Info.plist’ of your project, to make the application use the Subclass instead of NSApplication:

... <key>NSPrincipalClass</key> <string>MYApplicationWithPropsContainer</string>
3. now you can set your applicationwide properties:

call method "setProperty:forKey:" with parameters {thevalue, "theKey"}

and 4. retrieve it from anywhere in the application:

set valueForTheKey to (call method "propertyForKey:" with parameter "theKey")

Hi,

I wonder if we will get proper Globals in Leopard.

Not long to wait until we find out.

If we do I think there will be a lot of script rewriting.

All the best

Sweet! I’ve been wondering about that myself. Thanks for the great example there Dominik. :slight_smile:

Dominik,

Will try your global code when I get home.

How would you use it to deal with say a list of file paths.

Say I wanted to retrieve path 10 out of a list of 200 file paths.

Could you do this somehow or would it be necessary to get them all into an ASS variable first?

With all global schemes speed of dealing with lists seems to be the issue for me.

With user defaults you seem to have to load the full list to get at one item.

Is there anyway around this with your method?

All the best

Terry

Well, the Objective-C seems to have worked fine, and it all compiles…but if I try to store my property “stats” using this:


call method "setProperty:forKey" with parameters {stats, "stats"}
show window "third_options"

And then use this in my other script:


on became main theObject
	set stats to (call method "propertyForKey:" with parameter "stats")
	log (stats)
end became main

I get an error about stats being undefined. (-2753)

I’m sure that there’s probably just a small typo or something that I’ve missed, but I’ve double-checked the Objective-C and it’s fine - do you have any ideas on why the value might not be getting set?

Thanks again for all your help,
Girasquid

I might not be the expert on the code that Dominik gave us, but why not just save each value in the list as a numbered key? Something like filepath1->filepath200 or something - and then just doing something like this:


set tenthFilePath to (call method "propertyForKey" with parameter "filepath" & 10 as string)

Hi girasquid,

in your method call there’s a colon missing :wink:

call method “setProperty:forKey:” with parameters {stats, “stats”}

Hope that helps …

D.

Hi Terry,

of course it should be possible to set lists or records as property with this method and then you can access the items of these objects directly:

set myBigList to {“item1”, “item2”, “item3”, “item4”}
call method “setProperty:forKey:” with parameters {myBigList, “bigList”}

set item3ofBigList to (item 3 of (call method “propertyForKey:” with parameter "bigList))
→ “item3”

or by using another call method:

set item3ofBigList to (call method “objectAtIndex:” of (call method “propertyForKey:” with parameter "bigList) with parameter 2)
→ “item3”

but I don’t think there’s a big difference in performance between item … of and the call method (if there is one at all).

D.

Hi Dominik,

Thanks for the update.

Unfortunately, at work on a PC.

Will try it all out when I get home.

All the best

Terry

That fixed the problem.

Thanks so much for your help. I really feel like you’ve gone above-and-beyond.

Edit: one last(hopefully minor) issue.

I have a table view that I’m updating, using the regular event handler and the sample code for table views without data sources. There’s a conditional that goes like this:


if ((count of property) ≥ theRow) then
...

And then whatever you need to do gets done. I’m pretty sure that the conditional is just good practice to avoid awkward problems if an improper row is requested or something, but…it doesn’t compile. If I comment out that conditional it compiles fine, but that conditional breaks things. Does anyone know what could be wrong in that statement?

Also, is there a way to make it so a user can’t select any rows in a table view, but I can still select them programmatically and have them highlight? I want to highlight rows to show what’s changed, but not allow the user to change which row is selected.

Hi girasquid,

I’m not sure if I really understood … here an attempt to solve what I think i have understood:

to retrieve a count value of all properties you have set, you can add a method (somewhere between @implementation and @end):

-(int)countOfProperties{ return ([container count]); }
and/or a further method to retrieve all properties as record:

-(NSDictionary *)allProperties{ return ([NSDictionary dictionaryWithDictionary:container]); }
and add these line(s) after the other methods in @Interface:

-(int)countOfProperties; -(NSDictionary *)allProperties;
so if your problem is getting the count of all properties in your script you might use:

if ( (call method "countOfProperties") ≥ theRow) then ...

or to retrieve all properties:

set allProps to (call method "allProperties")

which you can access then as any other AppleScript record:

set valueForTheKey to (theKey of allProps)

Does this solve your problem?

D.

Sorry, I wasn’t very clear there. I actually meant something like this:


if ((count of foo) ≥ theRow) then

Which I resolved by changing to this:


if((count of foo) greater than or equal to theRow) then

I’m having a different dilemna now, however - is there a way to make it so that a user can’t select any rows in a table view, but I can still use applescript to select/highlight them? I want to highlight rows that have changed, but not let the user change which row is selected.