Difference between revisions of "Mac Preferences Read and Write"

From Lazarus wiki
Jump to navigationJump to search
m (→‎See also: added alsos)
(Added External links section for Apple docs)
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Platform only|macOS|macOS|macOS}}
+
{{Platform only|macOS}}
 +
{{Mac Preferences Read and Write}}
 +
 
 +
== macOS File Storage Overview ==
 +
{{macOS file storage}}
 +
 
 +
== Preferences ==
  
 
For those who want to read and write preferences for a macOS application, this can be done using the following methods:
 
For those who want to read and write preferences for a macOS application, this can be done using the following methods:
Line 13: Line 19:
  
 
   var
 
   var
     IValid: Boolean;
+
     IsValid: Boolean; // On return indicates if key exists and has valid data
 
     Pref: Integer;
 
     Pref: Integer;
  
Line 19: Line 25:
 
   begin
 
   begin
 
     try
 
     try
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check1'),kCFPreferencesCurrentApplication,IValid);
+
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check1'),kCFPreferencesCurrentApplication,IsValid);
 
       if (Pref = 1) then
 
       if (Pref = 1) then
      begin
+
           CheckBox1.Checked := true
           CheckBox1.Checked := true;
+
       else
      end
 
       else begin
 
 
           CheckBox1.Checked := false;
 
           CheckBox1.Checked := false;
      end;
+
 
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check2'),kCFPreferencesCurrentApplication,IValid);
+
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check2'),kCFPreferencesCurrentApplication,IsValid);
 
       if (Pref = 1) then
 
       if (Pref = 1) then
      begin
+
           CheckBox2.Checked := true
           CheckBox2.Checked := true;
+
       else
      end
 
       else begin
 
 
           CheckBox2.Checked := false;
 
           CheckBox2.Checked := false;
      end;
+
 
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check3'),kCFPreferencesCurrentApplication,IValid);
+
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check3'),kCFPreferencesCurrentApplication,IsValid);
 
       if (Pref = 1) then
 
       if (Pref = 1) then
      begin
+
           CheckBox3.Checked := true
           CheckBox3.Checked := true;
+
       else
      end
 
       else begin
 
 
           CheckBox3.Checked := false;
 
           CheckBox3.Checked := false;
      end;
+
 
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check4'),kCFPreferencesCurrentApplication,IValid);
+
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check4'),kCFPreferencesCurrentApplication,IsValid);
 
       if (Pref = 1) then
 
       if (Pref = 1) then
      begin
+
           CheckBox4.Checked := true
           CheckBox4.Checked := true;
+
       else
      end
 
       else begin
 
 
           CheckBox4.Checked := false;
 
           CheckBox4.Checked := false;
      end;
+
 
 
     except
 
     except
 
       on E : Exception do
 
       on E : Exception do
Line 73: Line 71:
 
     ItemVal: CFPropertyListRef;
 
     ItemVal: CFPropertyListRef;
  
   procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+
   procedure TForm1.FormClose(Sender: TObject);
 
   begin
 
   begin
 
     try
 
     try
 
       if (CheckBox1.Checked) then
 
       if (CheckBox1.Checked) then
      begin
+
        begin
          ItemName := CFStr('Check1');
+
          ItemName := CFStr('Check1');
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
      end
+
        end
       else begin
+
       else
          ItemName := CFStr('Check1');
+
        begin
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
+
          ItemName := CFStr('Check1');
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
      end;
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
 +
        end;
 +
 
 
       if (CheckBox2.Checked) then
 
       if (CheckBox2.Checked) then
      begin
+
        begin
          ItemName := CFStr('Check2');
+
          ItemName := CFStr('Check2');
          ItemVal := CFStringCreateWithPascalString(nil,'1',kCFStringEncodingUTF8);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
      end
+
        end
       else begin
+
       else  
          ItemName := CFStr('Check2');
+
        begin
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
+
          ItemName := CFStr('Check2');
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
      end;
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
 +
        end;
 +
     
 
       if (CheckBox3.Checked) then
 
       if (CheckBox3.Checked) then
      begin
+
        begin
          ItemName := CFStr('Check3');
+
          ItemName := CFStr('Check3');
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
      end
+
        end
       else begin
+
       else
          ItemName := CFStr('Check3');
+
        begin
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
+
          ItemName := CFStr('Check3');
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
      end;
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
 +
        end;
 +
 
 
       if (CheckBox4.Checked) then
 
       if (CheckBox4.Checked) then
      begin
+
        begin
          ItemName := CFStr('Check4');
+
          ItemName := CFStr('Check4');
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
      end
+
        end
       else begin
+
       else
          ItemName := CFStr('Check4');
+
        begin
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
+
          ItemName := CFStr('Check4');
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
+
          ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
      end;
+
          CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
 +
        end;
 +
 
 
       CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
 
       CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
 +
 
     except
 
     except
    on E : Exception do
+
      on E : Exception do
 
         ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
 
         ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
 
     end;
 
     end;
Line 131: Line 138:
  
 
== See also ==
 
== See also ==
 +
 
*[[Introduction to platform-sensitive development]]
 
*[[Introduction to platform-sensitive development]]
 
*[[Multiplatform_Programming_Guide#Proper_macOS_file_locations|Proper macOS file locations]]
 
*[[Multiplatform_Programming_Guide#Proper_macOS_file_locations|Proper macOS file locations]]
*[[OS X Programming Tips]]
+
*[[macOS Programming Tips]]
 +
 
 +
== External links ==
  
[[Category:Mac OS X]]
+
*[https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/AccessingPreferenceValues/AccessingPreferenceValues.html#//apple_ref/doc/uid/10000059i-CH3-108766 Apple: Managing Preferences Using Core Foundation]
[[Category:Platform-sensitive development]]
+
*[https://developer.apple.com/documentation/foundation/preferences Apple: Preferences]
 +
*[https://developer.apple.com/documentation/corefoundation/preferences_utilities Apple: Preference Utilities]
 +
*[https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/Introduction/Introduction.html Apple: About Preferences and Settings]
 +
*[https://developer.apple.com/design/human-interface-guidelines/macos/app-architecture/preferences/ Apple: Human Interface Guidelines -Preferences]

Revision as of 07:57, 31 May 2020

macOSlogo.png

This article applies to macOS only.

See also: Multiplatform Programming Guide

English (en)

macOS File Storage Overview

Before we go any further, let's recap where the Apple Guidelines indicate your application should store its files:

  • Use the /Applications or /Applications/Utilities directory for the application bundle. The application bundle should contain everything: libraries, dependencies, help, every file that the application needs to run except those created by the application itself. If the application bundle is copied to another machine's /Applications or /Applications/Utilities directory, it should be able to run. Installing to these folders requires Admin privileges. The data in these folders is backed up by Time Machine.
  • Use the ~/Applications directory should Admin privileges not be available. This is the standard location for a single user application. This directory should not be expected to exist. The application bundle should contain everything: libraries, dependencies, help, every file that the application needs to run except those created by the application itself. If the application bundle is copied to another machine's /Applications or /Applications/Utilities directory, it should be able to run. This data is backed up by Time Machine.
  • Use the Application Support directory (this data is backed up by Time Machine), appending your <bundle_ID>, for:
    • Resource and data files that your application creates and manages for the user. You might use this directory to store application state information, computed or downloaded data, or even user created data that you manage on behalf of the user.
    • Autosave files.
  • Use the Caches directory (this is not backed up by Time Machine), appending your <bundle_ID>, for cached data files or any files that your application can recreate easily.
  • Use CFPreferences to read and write your application's preferences. This will automatically write preferences to the appropriate location and read them from the appropriate location. This data is backed up by Time Machine.
  • Use the application Resources directory (this is backed up by Time Machine) for your application-supplied image files, sound files, icon files and other unchanging data files necessary for your application's operation.
  • Use NSTemporaryDirectory (this is not backed up by Time Machine) to store temporary files that you intend to use immediately for some ongoing operation but then plan to discard later. Delete temporary files as soon as you are done with them.

Preferences

For those who want to read and write preferences for a macOS application, this can be done using the following methods:

CODE FOR READING PREFERENCES
  uses MacOSAll, CFPreferences;

  var
    IsValid: Boolean;  // On return indicates if key exists and has valid data
    Pref: Integer;

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    try
       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check1'),kCFPreferencesCurrentApplication,IsValid);
       if (Pref = 1) then
          CheckBox1.Checked := true
       else
          CheckBox1.Checked := false;

       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check2'),kCFPreferencesCurrentApplication,IsValid);
       if (Pref = 1) then
          CheckBox2.Checked := true
       else
          CheckBox2.Checked := false;

       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check3'),kCFPreferencesCurrentApplication,IsValid);
       if (Pref = 1) then
          CheckBox3.Checked := true
       else
          CheckBox3.Checked := false;

       Pref := CFPreferencesGetAppIntegerValue(CFStr('Check4'),kCFPreferencesCurrentApplication,IsValid);
       if (Pref = 1) then
          CheckBox4.Checked := true
       else
          CheckBox4.Checked := false;

    except
      on E : Exception do
        ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
    end;
  end;


CODE FOR WRITING PREFERENCES
  uses MacOSAll, CFPreferences;

  var
    ItemName: CFStringRef;
    ItemVal: CFPropertyListRef;

  procedure TForm1.FormClose(Sender: TObject);
  begin
    try
       if (CheckBox1.Checked) then
         begin
           ItemName := CFStr('Check1');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end
       else
         begin
           ItemName := CFStr('Check1');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end;

       if (CheckBox2.Checked) then
         begin
           ItemName := CFStr('Check2');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end
       else 
         begin
           ItemName := CFStr('Check2');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end;
       
       if (CheckBox3.Checked) then
         begin
           ItemName := CFStr('Check3');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end
       else
         begin
           ItemName := CFStr('Check3');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end;

       if (CheckBox4.Checked) then
         begin
           ItemName := CFStr('Check4');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'1',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end
       else
         begin
           ItemName := CFStr('Check4');
           ItemVal := CFStringCreateWithPascalString(kCFAllocatorDefault,'0',kCFStringEncodingUTF8);
           CFPreferencesSetAppValue(ItemName,ItemVal,kCFPreferencesCurrentApplication);
         end;

       CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);

     except
       on E : Exception do
         ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
     end;

Prefs1.png


See also

External links