Pathcontrol - save/load to/from shared user default

Hi everyone,

in a project I am trying to open an applicationpath with a path control and want to store the choosen URL to the shared user default to be able to load the application in the path control when relaunching my app.

I get the path and if I just go ahad and inside my app try this:


set myPath to pathControl's |URL|() --get the path
pathControl's setURL_(myPath) --sets the path

it works perfectly.

If try to save myPath I get the console message:

I understand this, though I don’t know what to do now.
I tried to convert the myPath so I could save it, but then I wasnt able to insert that path back into the pathcontrol.
console message looked like that:

Any ideas?

Thanks in advance!

Hi,

a string starting with file:// is a string representation of a file URL (Cocoa class NSURL).
NSUserDefaults accepts only property list compatible classes

If you’re loading and saving the value via bindings you have to add a value transformer (NSValueTransformer) to convert NSURL to NSString and vice versa

Hi Stefan,

ok … that is a good hint. Searching the forum I found an older post from someone having the same problem/question.
http://macscripter.net/viewtopic.php?id=38779

You posted some code to implement in a .h which is a subclass of NSValueTransformer.
… I get stuck at this point as it is giving me a couple of warnings when I try to build the project like:

in the .h in the first line:

@implementation PathTransformer : NSObject

I guess I need to add some more code to my applescript file / do some stuff in IB … right?

the contents of the .h file must be


@interface PathTransformer : NSValueTransformer

@end

sorry :frowning: … somthing’s still off.
let me post the whole code … maybe that makes it easier to tell what I am doing wrong.

My Interfache contains of a pathcontrol and a button.

appdelegate.applescript:


script AppDelegate
    property parent : class "NSObject"
    
    property pathControl : missing value -- bound to the pathcontrol in IB
    property appp01 : missing value -- apppath
    property defaults : missing value -- for storing the defaults
    
    on clickGet_(sender)
        set appp01 to pathControl's |URL|()
        -- I guess I am missing the convertion part here
        tell defaults to setObject_forKey_(appp01, "storedPath")
    end clickGet_
	
	on applicationWillFinishLaunching_(aNotification)
              tell current application's NSUserDefaults to set defaults to standardUserDefaults()
              tell defaults to set appp01 to objectForKey_("AppPath01")
              -- I guess I am missing the backconvertion part here
              pathControl's setURL_(appp01)
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		return current application's NSTerminateNow
	end applicationShouldTerminate_
	
end script

PathTransformer.h:


#import <Cocoa/Cocoa.h>

@interface BFPathTransformer : NSValueTransformer {
   
}

@end

PathTransformer.m


#import "BFPathTransformer.h"

@implementation BFPathTransformer

+ (Class)transformedValueClass
{
    return [NSURL class];
}

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

- (id)transformedValue:(id)value
{
    return (value) ? [NSURL fileURLWithPath:value] : nil;
}

- (id)reverseTransformedValue:(id)value
{
    return [value path];
}

@end

The convertion part (.m/.h) as I mentioned was copied from another thread.

there are two different options:

Load and save user defaults via bindings (without code)

NSValueTransformer is needed, but the other way round

#import "BFPathTransformer.h"

@implementation BFPathTransformer

+ (Class)transformedValueClass
{
return [NSString class];
}

+ (BOOL)allowsReverseTransformation
{
return YES;
}

- (id)transformedValue:(id)value
{
return (value) ? [value path] : nil;
}

- (id)reverseTransformedValue:(id)value
{
return (value) ? [NSURL fileURLWithPath:value] : nil;
}

@end

bind the appropriate key path to the NSSharedUserDefaultsController and select your value transformer

Load and save user defaults programmatically

the value transformer is not needed

load:

tell current application's NSUserDefaults to set defaults to standardUserDefaults()
tell defaults to set appp01 to objectForKey_("storedPath")
pathControl's setURL_(current application's |NSURL|'s fileURLWithPath_(appp01))

save:

tell current application's NSUserDefaults to set defaults to standardUserDefaults()
set appp01 to pathControl's |URL|()'s |path|()
tell defaults to setObject_forKey_(appp01, "storedPath"))
tell defaults to synchronize()

code is not tested, but you will see the way

ahhhh… ok … I see…
thanks for your fast reply! I’ll give it a shot later and let you know!

Awesome! :slight_smile:
I used the second way (the code one) and it worked like a charm.
Thanks for sharing your knowledge!