Preference Bundles
A preference bundle is how your tweak gets a settings pane. There are two kinds: declarative, described entirely by a plist, and a view controller you write yourself.
Bundles install to
/Library/TweakInject/Preferences/PreferenceBundles/. Declare a
dependency on com.doraorak.preferenceloaderx if you want the
pane to appear in System Settings as well as in the app.
Declarative
A Root.plist describing rows. No code, so nothing to load and
nothing to crash. Prefer this unless you need a control the format cannot
express.
<plist version="1.0">
<dict>
<key>title</key><string>MyTweak</string>
<key>items</key>
<array>
<dict>
<key>cell</key><string>PSSwitchCell</string>
<key>label</key><string>Enabled</string>
<key>key</key><string>enabled</string>
<key>default</key><true/>
</dict>
<dict>
<key>cell</key><string>PSSliderCell</string>
<key>label</key><string>Intensity</string>
<key>key</key><string>intensity</string>
<key>min</key><real>0.0</real>
<key>max</key><real>1.0</real>
<key>default</key><real>0.5</real>
</dict>
</array>
</dict>
</plist>
The key of each row is the preference key your tweak reads. The
domain comes from the bundle's Info.plist.
Info.plist
<key>CFBundleIdentifier</key><string>com.example.mytweakprefs</string> <key>NSPrincipalClass</key><string>MyPrefsController</string> <key>title</key><string>MyTweak</string> <key>defaults</key><string>com.example.mytweak</string> <key>icon</key><string>icon.svg</string>
defaults is the domain. It has to be the same string your tweak
reads from, or the pane writes where nothing is looking.
NSPrincipalClass is only needed for a custom pane.
Custom panes
Write a view controller and adopt PSPreferenceController, which tells you the domain and when the pane appears and disappears.
A custom pane is loaded as code into the app. That is why the app requests the entitlement to disable library validation: your bundle is signed by you, not by this project, and validation would otherwise refuse it. Declarative panes are data and are unaffected.
Reading the values back
From the tweak, use PSUserDefaults with the same domain, and register the same defaults the plist declares so both sides agree before anything has been written.