SU2018 with MacOS - .plist File Access

I’ve had a number of new and existing clients who are running SU2018 on MacOS who are reporting that they are unable to save global settings for the Medeek Truss Plugin. The problem is that no one is seeing any errors generated in the ruby console so I am currently at a loss on the exact problem and how to solve it.

Has anyone seen a similar issue and have been able to resolve it?

The code to write the global settings is very simple, an example below:

# Writes Materialsoption Setting

@Materialsoption_write_result = Sketchup.write_default "MEDEEK_TRUSS_PLUGIN", "MATERIALS_OPTION", @Materialsoption_new

Why would this stop working on SU2018 running on MacOS?

they were stored in the SU .plist which updated instantly, in v2018 they are stored in a .json file that updates ‘on quit’…

the old settings don’t get transferred to the new list, although you could to do that from ruby…

your code works and will retrieve from memory any ‘current session’ changes from any document in that session, using read_default [even though the file is not updated ]…

what code do you use to retrieve the defaults?

john

This is my code to read in the default settings:

# Reads in Materialsoption Setting

	@Materialsoption_db = Sketchup.read_default "MEDEEK_TRUSS_PLUGIN", "MATERIALS_OPTION"

	if @Materialsoption_db
		# Do Nothing
	else
		@Materialsoption_write_result = Sketchup.write_default "MEDEEK_TRUSS_PLUGIN", "MATERIALS_OPTION", "OFF"
		@Materialsoption_db = "OFF"
	end

that runs as expected [on El Capitan]…

maybe @slbaumgartner can test on High Sierra and see if there are issues…

john

Perhaps the json file is encoding “picky” ?

Do you have a “magic” encoding comment as the first line in your code ?

# encoding: UTF-8

Disappointing …

Not “user friendly”. Who will the user blame when a glitch causes the settings not to be stored ?


@medeek You might think about writing to and reading from, your own json file.

require 'json'

# Where @options is a local Hash or OpenStruct instance object.

def save_options(filepath)
  json_str = JSON.generate(@options)
  File.open(filepath,"w:UTF-8:#{__ENCODING__}") {|io| io.write(json_str) }
rescue => e
  # Notify user there was an error saving options.
end

def retrieve_options(filepath)
  if File::exist?(filepath)
    json_str = File.read(filepath,"r:UTF-8:#{__ENCODING__}")
    @options = JSON.parse(json_str)
  else
    save_options(filepath)
  end
rescue => e
  # Notify user there was an error retrieving options.
end

Or, yaml or whatever works.
The Ruby standard library also has a PStore lib which is very similar to json.

Will there be any issues with json and running this code on a Mac?

The real problem I guess I am having is that I have a lot of people that are running on Mac’s and when they have a problem I have no way right now of debugging since I don’t currently own a Mac.

So what your basically saying Dan is that I should probably not be using the read_default and write_default methods for storing my global settings?

I do not have a Mac, so test. Generally Mac were long Unicode aware before PCs were.

The code in this example is Ruby 2+ (SU2014+) as it uses string encoding.

It is meant to show that reading and writing your own file with a JSON string is “not rocket science”.

Steve is weighing in …

Away from my computer. I’ll take a look after I get home.

2 Likes

I’m looking into buy a used MacBook Pro 2012, with either Yosemite or El Capitan running on it. I’m going to assume that these MacOS’s will work with SU2017 or SU2018Pro.

Assuming is great, reading is better:

2 Likes

Well, it has been problematic since the beginning. It has a weird quirk that the values read from the registry on PC, are passed through eval() which is dangerous !

Many extension authors have long ago abandoned read_default and write_default and all it’s problems.

As I showed in the above code, the JSON module can convert an entire Hash (or OpenStruct) to the storage format and back using single method calls.
In the past I had to write an iterator to iterate my options hashes and repeatedly call read_default and write_default.


Now you have the option of writing your plugin settings in a version independant location, rather than having different settings for every version of SketchUp.

Basically you create a "Medeek" folder under the "%AppData%/SketchUp" folder, or directly in the "%AppData%" folder just like every other software company. So for example …

appdata = File::expand_path('../../..',Sketchup::find_support_file('Plugins'))

… returns the great-grandparent folder of the current SketchUp "Plugins" folder.
(This is the "SketchUp" software company folder. Add another generation to get to AppData on PC, or Application Support on Mac.) Then …

dirpath = File::join(appdata,"Medeek")
Dir::mkdir(dirpath) unless Dir::exist?(dirpath)
plugpath = File::join(dirpath,"TrussMaker") # <--- whatever the plugin brandname is ?
Dir::mkdir(plugpath) unless Dir::exist?(plugpath)
# use ... 
retrieve_options(plugpath)
1 Like

As Mike showed, the official report is that Yosemite is now unsupported, and El Capitan is next on the chopping block. Has Apple announced what the next version of OSX will be ?

I’d aim for something that can run Sierra as a minimum (High Sierra even better.)

1 Like

I wish someone had warned me about the problems with read_default and write_default. All my global settings use these so to rewrite this module is a bit of work, but it can be done.

There are numerous topic threads on this over at SketchUcation. Perhaps a few here.

I was reading the 2018 release notes and I happened upon this section:

Preferences Location
The majority of preferences are now stored in two json files. There are still some OS controlled preferences that remain in the registry (Win) or plist (Mac). The json files are saved in the following locations:

On Win:
PrivatePreferences.json is saved to C:\Users\AppData\Local\SketchUp\SketchUp 2018\SketchUp SharedPreferences.json is saved to C:\Users\AppData\Roaming\SketchUp\SketchUp 2018\SketchUp

On Mac:
Both PrivatePreferences.json and SharedPreferences.json are saved to /Users//Library/Application Support/SketchUp 2018/SketchUp

Maybe this is what is breaking the plugin…

Not yet, but it’ll be macOS 10.14 (plus a silly name) sometime in late 2018. They’ve been releasing them annually for a while now.

1 Like

I just now realized that in SU2018 the global settings are actually store in the JSON files as noted in the release notes above, that is a big change.

1 Like

Are they all separate module variables ?

Do they have anything in common in their name that can be used to collect them ? … a substring “option” ?

# within a module or class ...
@options = {}
vars = class_variables.find_all {|var| var =~ /option/ }
vars.each do |var|
  @options[var.to_s[3..-1].to_sym]= class_variable_get(var)
end
# pass @options hash to methods above ...

I’ll send you the settings .rb file so you can tell me what you think, you’ll probably laugh at how inefficient my programming is.

Anyway you cut it, its going to be some work. Since SU is migrating away from the registry and plist and using json I might as well create my own json, that way it doesn’t get broken in the future by another SU curve ball.