Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198
PreferenceLoader: Difference between revisions - iPhone Development Wiki

PreferenceLoader: Difference between revisions

From iPhone Development Wiki
(Extended description, reordered keys, explanation of each approach, pl_filter usage correction, formatting)
(Update versions.)
(16 intermediate revisions by 3 users not shown)
Line 2: Line 2:
|screenshot=PrefLoaderScreenshot.png
|screenshot=PrefLoaderScreenshot.png
|developer=[[User:Dustin Howett|Dustin Howett]]
|developer=[[User:Dustin Howett|Dustin Howett]]
|version=2.2.0-1
|version=2.2.3-3<br />2.2.4~beta1
|package=preferenceloader
|package=preferenceloader
}}
}}
Line 13: Line 13:


== Entry file ==
== Entry file ==
{{main|Preferences specifier plist}}


Each entry is defined in its own plist. There are at least three ways to approach preferences support for your tweaks.
Each entry is defined in its own plist. There are at least three ways to approach preferences support for your tweaks.
Line 48: Line 50:
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>.
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>.


== Simple Approach ==
=== Simple Approach ===


Provides a pane where other cells can appear (like Wi-Fi). Recommended for configuration-friendly tweaks. Here's an example:
Provides a pane where other cells can appear (like Wi-Fi). Recommended for configuration-friendly tweaks. Here's an example:
Line 95: Line 97:
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].
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].


=== Localization<ref name="1.2">PreferenceLoader version 1.2 and later</ref> ===
=== PreferenceBundle Approach ===
 
Instead of placing the entry plist in <tt>/Library/PreferenceLoader/Preferences/</tt>, place it in a subfolder in that directory along with the  .lproj folders containing a strings file named <tt>Localizable.strings</tt>.
 
== 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:
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:
Line 129: Line 127:
== Filtering<ref name="2.2.0-1">PreferenceLoader version 2.2.0-1 and later</ref> ==
== 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]], developers may add filters to entry plists and specifiers within simple and localized simple preferences. The filter should be a dictionary at the top level of the entry plist, or within a specifier, which can contain these keys:
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.
* '''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}}
{{CoreFoundation Version Table|center=1}}


Below sample specifier will be filter for iOS 6.0 or later.
Below sample specifier will filter for iOS 6.0 or later.
<source lang="xml">
{|
|- 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>
<dict>
<key>cell</key>
<key>cell</key>
Line 153: Line 174:
</array>
</array>
</dict>
</dict>
</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>
</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}}
|}


== Issues with OS 3.2 and 4.0 ==
<tt>PSViewController</tt> underwent a massive change after 3.1, breaking all custom subclasses on the iPad and on 4.0 - it is now a UIViewController.


Improper implementations of <tt>PSListController</tt> subclasses will fail to work properly on 4.0. You must set <tt>_specifiers</tt> within the <tt>-(id) specifiers</tt> method (instead of returning a different array of specifiers.) This is because OS 4.0 relies on _specifiers to generate specifier metadata and group indices. Example:
{|
<source lang="objc">
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/en.lproj/a.strings
- (id) specifiers {
|- valign="top"
if (!_specifiers){
|
_specifiers = [[self loadSpecifiersFromPlistName: kNameOfPreferencesPlist target: self] retain];
{{Collapse|1=<source lang="javascript">{
}
BREAD = "Bread and cheese";
FOOD = Food;
return _specifiers;
}
}
</source>
</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


== Notes ==
== References ==
<references />
<references />


== References ==
== See also ==
<div class="references-2column">
 
* [[PreferenceBundles]]
* [[Preferences specifier plist]]
* [[Preferences specifier plist]]
== External links ==
* [http://jontelang.com/guide/chapter3/the-settings.html Settings how to]
* [http://jontelang.com/guide/chapter3/the-settings.html Settings how to]
</div>


{{Navbox Library}}
{{Navbox Library}}
[[Category:Directories in /Library]]
[[Category:Directories in /Library]]
[[Category:Preferences]]

Revision as of 14:45, 5 September 2019

PreferenceLoader
Error creating thumbnail: File missing
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 CoreFoundation version
2.0 478.23
2.1 478.26.1
2.2 478.29
3.0 478.47.7
3.1 478.52
3.2 478.61
4.0 550.32
4.1 550.38.1
4.2 550.52
4.3 550.58.1
5.0 675.00
5.1 690.10
6.0 793.00
6.1 793.00
7.0 847.20
7.1 847.24
8.0 1140.10
8.1 1141.14
8.2 1142.16
8.3 1144.17
8.4 1145.15
9.0 1240.10
9.1 1241.11
9.2 1242.13
9.3 1280.38
10.0 1348.00
10.1 1348.00
10.2 1348.22
10.3 1349.56
11.0 1443.00
11.1 1445.32
11.2 1450.14
11.3 1452.23
11.4 1452.23
12.0 1556.00
12.1 1560.10
12.2 1570.15
12.3 1575.13
12.4 1575.17
12.5 1575.23
13.0 1665.15
13.1 1671.101
13.2 1673.126
13.3 1674.102
13.4 1675.129
13.5 1676.104
13.6 1677.104
13.7 1677.104
14.0 1751.108
14.1 1751.108
14.2 1770.106
14.3 1770.300
14.4 1774.101
14.5 1775.118
14.6 1776.103
14.7 1777.103
14.8 1778.101
15.0 1854
15.1 1855.105
15.2 1856.105
15.3 1856.105
15.4 1858.112

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