Difference between revisions of "PreferenceLoader"

From iPhone Development Wiki
Jump to: navigation, search
(Created page with 'PreferenceLoader is a MobileSubstrate based utility that allows developers to add entries to the Settings app, similar to the SettingsBundles that app store apps use. The approa…')
 
(Update versions.)
 
(40 intermediate revisions by 11 users not shown)
Line 1: Line 1:
PreferenceLoader is a MobileSubstrate based utility that allows developers to add entries to the Settings app, similar to the SettingsBundles that app store apps use.
+
{{Infobox Package
 +
|screenshot=PrefLoaderScreenshot.png
 +
|developer=[[User:Dustin Howett|Dustin Howett]]
 +
|version=2.2.3-3<br />2.2.4~beta1
 +
|package=preferenceloader
 +
}}
  
The approach PreferenceLoader takes is different that other approaches in that the Settings plist files are not modified on disk. Entries are dynamically added to the list when the Settings app is loaded. PreferenceLoader gives the developer two options for entries. The first option is to simply create a single plist with basic options like PSSwitchCell or PSEditTextCell. The second option is allows the developer to create a full-blown PreferencesBundle.
+
'''PreferenceLoader''' is an open-source<ref>[http://github.com/DHowett/preferenceloader PreferenceLoader Source]</ref> [[MobileSubstrate]] based utility that allows developers to add entries to the [[Preferences.app|Settings]] application, similar to the Settings bundles that AppStore apps use.
  
Regardless of the approach taken, each new entry is specified in its own plist located at /Library/PreferenceLoader/Preferences/. The plist must contain a dictionary containing a dictionary element named entry, as shown TestSettngs.plist:
+
The approach PreferenceLoader takes is different from other approaches in that the Settings-iPhone.plist and Settings-iPod.plist files are not modified on disk. When the [[Preferences.app|Settings]] application is loaded, entries are read from plists in <tt>/Library/PreferenceLoader/Preferences/</tt> and are dynamically added to the list before the AppStore applications' preferences group.
  
    <?xml version="1.0" encoding="UTF-8"?>
+
PreferenceLoader also allows [[PreferenceBundles]] to be loaded from <tt>/Library/PreferenceBundles/</tt><ref name="1.2">PreferenceLoader version 1.2 and later</ref><ref>Bundles can also be loaded from /System/Library/PreferenceBundles/, but this is no longer the preferred method as of PreferenceLoader 1.2</ref>.
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 
    <plist version="1.0">
 
    <dict>
 
          <key>entry</key>
 
          <dict>
 
                <key>cell</key>
 
                <string>PSLinkCell</string>
 
                <key>icon</key>
 
                <string>TestIcon.png</string>
 
                <key>label</key>
 
                <string>Test</string>
 
          </dict>
 
    </dict>
 
    </plist>
 
  
In this example, a new entry with the label Test is created that links to the settings page defined in Test.plist using the icon TestIcon.png. Both of these files should be placed in the Preferences directory with TestSettings.plist. One interesting thing that can be done is to combine the entry plist with the settings plist. This works because the settings plist has elements named items and title, so adding an entry element does not break anything. Here's an example of Test.plist that is combined:
+
== Entry file ==
  
    <?xml version="1.0" encoding="UTF-8"?>
+
{{main|Preferences specifier plist}}
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 
    <plist version="1.0">
 
    <dict>
 
          <key>entry</key>
 
          <dict>
 
                <key>cell</key>
 
                <string>PSLinkCell</string>
 
                <key>icon</key>
 
                <string>TestIcon.png</string>
 
                <key>label</key>
 
                <string>Test</string>
 
          </dict>
 
          <key>items</key>
 
          <array>
 
                <dict>
 
                      <key>cell</key>
 
                      <string>PSSwitchCell</string>
 
                      <key>default</key>
 
                      <true/>
 
                      <key>defaults</key>
 
                      <string>com.test.TestSettings</string>
 
                      <key>key</key>
 
                      <string>testKey</string>
 
                      <key>label</key>
 
                      <string>Test Setting</string>
 
                </dict>
 
          </array>
 
          <key>title</key>
 
          <string>Test</string>
 
    </dict>
 
    </plist>
 
  
There is a good tutorial on how to create these settings plists on MMi at: http://modmyi.com/forums/file-mods/22453-how-make-custom-menus-preferences-app-custom-preferences.html
+
Each entry is defined in its own plist. There are at least three ways to approach preferences support for your tweaks.
  
== PreferenceBundles ==
+
=== Reduced approach ===
  
For those of you that want to create more complex settings pages, then the PreferenceBundle is for you. With this technique, you can actually create custom pages that are able to execute code. Skylar Cantu has put together a very useful guide on PreferenceBundles at: http://www.touchrepo.com/guides/preferencebundles/PreferenceBundles.doc
+
Provides a switch on the root section of the preferences (like Airplane Mode). Recommended for configuration-less tweaks.
  
The only difference to his guide that is to be noted is that like the simple approach given above, the developer should create a plist in /Library/PreferenceLoader/Preferences/. Here's an example of an updated TestSettings.plist:
+
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<dict>
 +
<key>entry</key>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSSwitchCell</string>
 +
<key>defaults</key>
 +
<string>com.test.TestSettings</string>
 +
<key>label</key>
 +
<string>Test</string>
 +
<key>key</key>
 +
<string>enabled</string>
 +
<key>default</key>
 +
<true/>
 +
<key>icon</key>
 +
<string>TestIcon.png</string>
 +
<key>PostNotification</key>
 +
<string>com.test.TestSettings/preferences.changed</string>
 +
</dict>
 +
</dict>
 +
</plist>
 +
</source>
  
    <?xml version="1.0" encoding="UTF-8"?>
+
This sets up an entry called <code>Test</code> with an icon loaded from <code>TestIcon.png</code> to the left and a UISwitch on the right, starting in the ON position, saving the value in <code>[NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.test.TestSettings"]</code> for the key <tt>enabled</tt> and posting a Darwin notification named <code>com.test.TestSettings/preferences.changed</code>.
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 
    <plist version="1.0">
 
    <dict>
 
          <key>entry</key>
 
          <dict>
 
                <key>bundle</key>
 
                <string>TestSettings</string>
 
                <key>cell</key>
 
                <string>PSLinkCell</string>
 
                <key>icon</key>
 
                <string>TestIcon.png</string>
 
                <key>isController</key>
 
                <true/>
 
                <key>label</key>
 
                <string>Test</string>
 
          </dict>
 
    </dict>
 
    </plist>
 
  
The difference here is that instead of loading Test.plist, this entry will load the TestSettings.bundle located at /System/Library/PreferenceBundles/. Unlike the simple method, all of the files except TestSettings.plist are located inside the bundle. A skeleton PreferenceBundle project can be found at: http://www.volatile-dev.com/PreferenceLoader/TestSettings.zip
+
=== Simple Approach ===
 +
 
 +
Provides a pane where other cells can appear (like Wi-Fi). Recommended for configuration-friendly tweaks. Here's an example:
 +
 
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<dict>
 +
<key>entry</key>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSLinkCell</string>
 +
<key>icon</key>
 +
<string>TestIcon.png</string>
 +
<key>label</key>
 +
<string>Test</string>
 +
</dict>
 +
<key>title</key>
 +
<string>Test Settings</string>
 +
<key>items</key>
 +
<array>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSSwitchCell</string>
 +
<key>defaults</key>
 +
<string>com.test.TestSettings</string>
 +
<key>key</key>
 +
<string>enabled</string>
 +
<key>label</key>
 +
<string>Enabled</string>
 +
<key>default</key>
 +
<true/>
 +
<key>PostNotification</key>
 +
<string>com.test.TestSettings/preferences.changed</string>
 +
</dict>
 +
</array>
 +
</dict>
 +
</plist>
 +
</source>
 +
 
 +
This sets up an entry called <code>Test</code> with an icon loaded from <code>TestIcon.png</code> to the left. The pushed page has the title set to <tt>Test Settings</tt>. The page will only contain a cell with the label <tt>Enabled</tt> UISwitch on the right, starting in the ON position, saving the value in <code>[NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.test.TestSettings"]</code> for the key <tt>enabled</tt> and posting a Darwin notification named <code>com.test.TestSettings/preferences.changed</code>.
 +
 
 +
For more preferences values you can add [[Preferences_specifier_plist|specifier]] dictionaries to the <tt>items</tt> array.
 +
 
 +
There is a good tutorial on [http://modmyi.com/forums/file-mods/22453-how-make-custom-menus-preferences-app-custom-preferences.html how to create settings plists on MMi].
 +
 
 +
=== PreferenceBundle Approach ===
 +
 
 +
You can create custom settings pages that are able to execute code. This only requires a plist that loads a [[PreferenceBundles|PreferenceBundle]]. Here's an example:
 +
 
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<dict>
 +
<key>entry</key>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSLinkCell</string>
 +
<key>label</key>
 +
<string>Test</string>
 +
<key>icon</key>
 +
<string>TestIcon.png</string>
 +
<key>isController</key>
 +
<true/>
 +
<key>bundle</key>
 +
<string>TestSettings</string>
 +
</dict>
 +
</dict>
 +
</plist>
 +
</source>
 +
 
 +
This sets up an entry called <code>Test</code> with an icon loaded from <code>TestIcon.png</code> to the left. The rest of the details are up to the bundle named <tt>TestSettings</tt>.
 +
 
 +
== Filtering<ref name="2.2.0-1">PreferenceLoader version 2.2.0-1 and later</ref> ==
 +
 
 +
In a way similar to that of [[MobileSubstrate#MobileLoader|MobileSubstrate]], PreferenceLoader supports filters for entry plists and specifiers. The filter should be a dictionary for the key <tt>pl_filter</tt> which can contain these keys:
 +
 
 +
* '''CoreFoundationVersion''' (array): The entry or specifier is loaded or displayed only if the version of [[CoreFoundation.framework]] is above the specified value or within the specified range. Currently, only the first 2 values are checked.
 +
{{CoreFoundation Version Table|center=1}}
 +
 
 +
Below sample specifier will filter for iOS 6.0 or later.
 +
{|
 +
|- valign="top"
 +
|
 +
{{Collapse|1=<source lang="javascript">{
 +
cell = PSSwitchCell;
 +
defaults = "com.your.tweak";
 +
label = "Your Tweak";
 +
key = enabled;
 +
default = 1;
 +
icon = "/Applications/Preferences.app/icon-table@2x.png";
 +
PostNotification = "com.your.tweak/preferences.changed";
 +
pl_filter = {
 +
CoreFoundationVersion = (
 +
"793.00"
 +
);
 +
};
 +
}
 +
</source>|2=NeXTSTEP style}}
 +
||
 +
{{Collapse|1=<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<dict>
 +
<key>cell</key>
 +
<string>PSSwitchCell</string>
 +
<key>defaults</key>
 +
<string>com.test.TestSettings</string>
 +
<key>label</key>
 +
<string>Test Setting</string>
 +
<key>key</key>
 +
<string>testKey</string>
 +
<key>default</key>
 +
<true/>
 +
<key>pl_filter</key>
 +
<dict>
 +
<key>CoreFoundationVersion</key>
 +
<array>
 +
<string>793.00</string>
 +
</array>
 +
</dict>
 +
</plist>
 +
</source>|2=XML style}}
 +
|}
 +
 
 +
To provide a range specify the lower bound first (checked as "greater or equal than") and the upper bound second (checked as "less than").
 +
The filter below will filter for iOS 4.X.
 +
{|
 +
|- valign="top"
 +
| NeXTSTEP style || XML style
 +
|-
 +
|
 +
<source lang="javascript">{
 +
pl_filter = {
 +
CoreFoundationVersion = (
 +
"550.32",
 +
"675.00"
 +
);
 +
};
 +
}
 +
</source>
 +
||
 +
<source lang="xml">
 +
<key>pl_filter</key>
 +
<dict>
 +
<key>CoreFoundationVersion</key>
 +
<array>
 +
<string>550.32</string>
 +
<string>675.00</string>
 +
</array>
 +
</dict>
 +
</source>
 +
|}
 +
 
 +
== Localization<ref name="1.2">PreferenceLoader version 1.2 and later</ref> ==
 +
 
 +
Preferences.framework can localize strings in specifier properties, such as titles and labels.
 +
 
 +
Place your specifier plists and icons in a folder within <tt>/Library/PreferenceLoader/Preferences/</tt>. For each <tt>file</tt>.plist file and for each language you have translations for, create a <tt>file</tt>.strings.
 +
 
 +
Here's an example:
 +
 
 +
{|
 +
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/a.plist
 +
|- valign="top"
 +
|
 +
{{Collapse|1=<source lang="javascript">{
 +
entry =    {
 +
cell = PSLinkCell;
 +
icon = "/Applications/Preferences.app/icon-table@2x.png";
 +
label = A;
 +
};
 +
items =    (
 +
{
 +
cell = PSLinkCell;
 +
label = b;
 +
},
 +
{
 +
cell = PSEditTextCell;
 +
footerAlignment = 1;
 +
keyboard = dvorak;
 +
label = FOOD;
 +
placeholder = BREAD;
 +
}
 +
);
 +
title = "PSSpecifier Localization";
 +
}
 +
</source>|2=NeXTSTEP style}}
 +
||
 +
{{Collapse|1=<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<key>entry</key>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSLinkCell</string>
 +
<key>icon</key>
 +
<string>/Applications/Preferences.app/icon-table@2x.png</string>
 +
<key>label</key>
 +
<string>A</string>
 +
</dict>
 +
<key>items</key>
 +
<array>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSLinkCell</string>
 +
<key>label</key>
 +
<string>b</string>
 +
</dict>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSEditTextCell</string>
 +
<key>footerAlignment</key>
 +
<string>1</string>
 +
<key>keyboard</key>
 +
<string>dvorak</string>
 +
<key>label</key>
 +
<string>FOOD</string>
 +
<key>placeholder</key>
 +
<string>BREAD</string>
 +
</dict>
 +
</array>
 +
<key>title</key>
 +
<string>PSSpecifier Localization</string>
 +
</plist>
 +
</source>|2=XML style}}
 +
|}
 +
 
 +
 
 +
{|
 +
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/en.lproj/a.strings
 +
|- valign="top"
 +
|
 +
{{Collapse|1=<source lang="javascript">{
 +
BREAD = "Bread and cheese";
 +
FOOD = Food;
 +
}
 +
</source>|2=NeXTSTEP style}}
 +
||
 +
{{Collapse|1=<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<key>BREAD</key>
 +
<string>Bread and cheese</string>
 +
<key>FOOD</key>
 +
<string>Food</string>
 +
</plist>
 +
</source>|2=XML style}}
 +
|}
 +
 
 +
 
 +
{|
 +
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/es.lproj/a.strings
 +
|- valign="top"
 +
|
 +
{{Collapse|1=<source lang="javascript">{
 +
BREAD = "Pan y queso";
 +
FOOD = Comida;
 +
}
 +
</source>|2=NeXTSTEP style}}
 +
||
 +
{{Collapse|1=<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<key>BREAD</key>
 +
<string>Pan y queso</string>
 +
<key>FOOD</key>
 +
<string>Comida</string>
 +
</plist>
 +
</source>|2=XML style}}
 +
|}
 +
 
 +
 
 +
{|
 +
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/b.plist
 +
|- valign="top"
 +
|
 +
{{Collapse|1=<source lang="javascript">{
 +
items =    (
 +
{
 +
cell = PSTitleValueCell;
 +
label = VEHICLE;
 +
value = CAR;
 +
}
 +
);
 +
title = "PSSpecifier Localization";
 +
}
 +
</source>|2=NeXTSTEP style}}
 +
||
 +
{{Collapse|1=<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<key>items</key>
 +
<array>
 +
<dict>
 +
<key>cell</key>
 +
<string>PSTitleValueCell</string>
 +
<key>label</key>
 +
<string>VEHICLE</string>
 +
<key>value</key>
 +
<string>CAR</string>
 +
</dict>
 +
</array>
 +
<key>title</key>
 +
<string>PSSpecifier Localization</string>
 +
</plist>
 +
</source>|2=XML style}}
 +
|}
 +
 
 +
 
 +
{|
 +
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/en.lproj/b.strings
 +
|- valign="top"
 +
|
 +
{{Collapse|1=<source lang="javascript">{
 +
CAR = Car;
 +
VEHICLE = Vehicle;
 +
}
 +
</source>|2=NeXTSTEP style}}
 +
||
 +
{{Collapse|1=<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<key>CAR</key>
 +
<string>Car</string>
 +
<key>VEHICLE</key>
 +
<string>Vehicle</string>
 +
</plist>
 +
</source>|2=XML style}}
 +
|}
 +
 
 +
 
 +
{|
 +
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/es.lproj/b.strings
 +
|- valign="top"
 +
|
 +
{{Collapse|1=<source lang="javascript">{
 +
CAR = Auto;
 +
VEHICLE = Vehiculo;
 +
}
 +
</source>|2=NeXTSTEP style}}
 +
||
 +
{{Collapse|1=<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 +
<plist version="1.0">
 +
<key>CAR</key>
 +
<string>Auto</string>
 +
<key>VEHICLE</key>
 +
<string>Vehiculo</string>
 +
</plist>
 +
</source>|2=XML style}}
 +
|}
 +
 
 +
== Example code ==
 +
 
 +
https://github.com/Sassoty/theos-examples/tree/master/preferenceloader
 +
 
 +
== References ==
 +
<references />
 +
 
 +
== See also ==
 +
 
 +
* [[PreferenceBundles]]
 +
* [[Preferences specifier plist]]
 +
 
 +
== External links ==
 +
 
 +
* [http://jontelang.com/guide/chapter3/the-settings.html Settings how to]
 +
 
 +
{{Navbox Library}}
 +
[[Category:Directories in /Library]]
 +
[[Category:Preferences]]

Latest revision as of 14:45, 5 September 2019

PreferenceLoader
PrefLoaderScreenshot.png
Cydia Package
Developer Dustin Howett
Package ID preferenceloader
Latest Version 2.2.3-3
2.2.4~beta1


PreferenceLoader is an open-source[1] MobileSubstrate based utility that allows developers to add entries to the Settings application, similar to the Settings bundles that AppStore apps use.

The approach PreferenceLoader takes is different from other approaches in that the Settings-iPhone.plist and Settings-iPod.plist files are not modified on disk. When the Settings application is loaded, entries are read from plists in /Library/PreferenceLoader/Preferences/ and are dynamically added to the list before the AppStore applications' preferences group.

PreferenceLoader also allows PreferenceBundles to be loaded from /Library/PreferenceBundles/[2][3].

Entry file

Each entry is defined in its own plist. There are at least three ways to approach preferences support for your tweaks.

Reduced approach

Provides a switch on the root section of the preferences (like Airplane Mode). Recommended for configuration-less tweaks.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>entry</key>
	<dict>
		<key>cell</key>
		<string>PSSwitchCell</string>
		<key>defaults</key>
		<string>com.test.TestSettings</string>
		<key>label</key>
		<string>Test</string>
		<key>key</key>
		<string>enabled</string>
		<key>default</key>
		<true/>
		<key>icon</key>
		<string>TestIcon.png</string>
		<key>PostNotification</key>
		<string>com.test.TestSettings/preferences.changed</string>
	</dict>
</dict>
</plist>

This sets up an entry called Test with an icon loaded from TestIcon.png to the left and a UISwitch on the right, starting in the ON position, saving the value in [NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.test.TestSettings"] for the key enabled and posting a Darwin notification named com.test.TestSettings/preferences.changed.

Simple Approach

Provides a pane where other cells can appear (like Wi-Fi). Recommended for configuration-friendly tweaks. Here's an example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>entry</key>
	<dict>
		<key>cell</key>
		<string>PSLinkCell</string>
		<key>icon</key>
		<string>TestIcon.png</string>
		<key>label</key>
		<string>Test</string>
	</dict>
	<key>title</key>
	<string>Test Settings</string>
	<key>items</key>
	<array>
		<dict>
			<key>cell</key>
			<string>PSSwitchCell</string>
			<key>defaults</key>
			<string>com.test.TestSettings</string>
			<key>key</key>
			<string>enabled</string>
			<key>label</key>
			<string>Enabled</string>
			<key>default</key>
			<true/>
			<key>PostNotification</key>
			<string>com.test.TestSettings/preferences.changed</string>
		</dict>
	</array>
</dict>
</plist>

This sets up an entry called Test with an icon loaded from TestIcon.png to the left. The pushed page has the title set to Test Settings. The page will only contain a cell with the label Enabled UISwitch on the right, starting in the ON position, saving the value in [NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.test.TestSettings"] for the key enabled and posting a Darwin notification named com.test.TestSettings/preferences.changed.

For more preferences values you can add specifier dictionaries to the items array.

There is a good tutorial on how to create settings plists on MMi.

PreferenceBundle Approach

You can create custom settings pages that are able to execute code. This only requires a plist that loads a PreferenceBundle. Here's an example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>entry</key>
	<dict>
		<key>cell</key>
		<string>PSLinkCell</string>
		<key>label</key>
		<string>Test</string>
		<key>icon</key>
		<string>TestIcon.png</string>
		<key>isController</key>
		<true/>
		<key>bundle</key>
		<string>TestSettings</string>
	</dict>
</dict>
</plist>

This sets up an entry called Test with an icon loaded from TestIcon.png to the left. The rest of the details are up to the bundle named TestSettings.

Filtering[4]

In a way similar to that of MobileSubstrate, PreferenceLoader supports filters for entry plists and specifiers. The filter should be a dictionary for the key pl_filter which can contain these keys:

  • CoreFoundationVersion (array): The entry or specifier is loaded or displayed only if the version of CoreFoundation.framework is above the specified value or within the specified range. Currently, only the first 2 values are checked.
Firmware 2.0 2.1 2.2 3.0 3.1 3.2 4.0 4.1 4.2 4.3 5.0 5.1
CoreFoundation version 478.23 478.26.1 478.29 478.47.7 478.52 478.61 550.32 550.38.1 550.52 550.58.1 675.00 690.10
Firmware 6.0 6.1 7.0 7.1 8.0 8.1 8.2 8.3 8.4 9.0 9.1 9.2 9.3
CoreFoundation version 793.00 847.20 847.24 1140.10 1141.14 1142.16 1144.17 1145.15 1240.10 1241.11 1242.13 1280.38
Firmware 10.0 10.1 10.2 10.3 11.0 11.1 11.2 11.3 11.4 12.0 12.1 12.2 12.3 12.4
CoreFoundation version 1348.00 1348.22 1349.56 1443.00 1445.32 1450.14 1452.23 1452.23 1556.00 1560.10 1570.15 1575.13 1575.17

Below sample specifier will filter for iOS 6.0 or later.

To provide a range specify the lower bound first (checked as "greater or equal than") and the upper bound second (checked as "less than"). The filter below will filter for iOS 4.X.

NeXTSTEP style XML style
{
	pl_filter = {
		CoreFoundationVersion = (
			"550.32",
			"675.00"
		);
	};
}
	<key>pl_filter</key>
	<dict>
		<key>CoreFoundationVersion</key>
		<array>
			<string>550.32</string>
			<string>675.00</string>
		</array>
	</dict>

Localization[2]

Preferences.framework can localize strings in specifier properties, such as titles and labels.

Place your specifier plists and icons in a folder within /Library/PreferenceLoader/Preferences/. For each file.plist file and for each language you have translations for, create a file.strings.

Here's an example:

/Library/PreferenceLoader/Preferences/Example/a.plist


/Library/PreferenceLoader/Preferences/Example/en.lproj/a.strings


/Library/PreferenceLoader/Preferences/Example/es.lproj/a.strings


/Library/PreferenceLoader/Preferences/Example/b.plist


/Library/PreferenceLoader/Preferences/Example/en.lproj/b.strings


/Library/PreferenceLoader/Preferences/Example/es.lproj/b.strings

Example code

https://github.com/Sassoty/theos-examples/tree/master/preferenceloader

References

  1. PreferenceLoader Source
  2. 2.0 2.1 PreferenceLoader version 1.2 and later
  3. Bundles can also be loaded from /System/Library/PreferenceBundles/, but this is no longer the preferred method as of PreferenceLoader 1.2
  4. PreferenceLoader version 2.2.0-1 and later

See also

External links