HBPreferences

@interface HBPreferences : NSObject

The HBPreferences class in Cephei provides an interface for managing user-defined preferences of a tweak, and the default values used when the user has not yet changed a value.

HBPreferences is very similar to NSUserDefaults, however it is specifically tailored to iOS tweak development, since tweaks may be loaded into a sandboxed process (most obviously, App Store apps, but also system apps like Safari), or one that runs as the root user (for instance, iFile, although these apps are slowly changing their model so they now run as mobile). In both of these cases, using NSUserDefaults will result in reading from preferences inside the sandbox, or inside root’s home directory; both of which are not what is expected.

Advantages HBPreferences has over NSUserDefaults are:

  • Directly reading the property list from the mobile user’s home directory, to support sandboxed apps and apps running as root.
  • Intuitive method of setting a default preference value.
  • Updating of the app/tweak’s variables when preferences are changed.
  • Keyed subscripting is allowed, which enables simple array syntax.
  • Values in the preferences plist are called preferences, not defaults, to avoid ambiguity - NSUserDefaults uses “defaults” to refer to both preferences themselves and the fallback values if a key doesn’t exist.

Ensure you read the discussion for -[HBPreferences registerObject:default:forKey:] before using the automatic updating mechanism. -[HBPreferences objectForKey:] does not update as another process updates the preferences on iOS 7 or older; if you need to support older iOS versions, use the registration methods instead.

Example usage

HBPreferences *preferences;
BOOL doThing;

%ctor {
    preferences = [[HBPreferences alloc] initWithIdentifier:@"ws.hbang.common.demo"];
    [preferences registerDefaults:@{
        @"Enabled": @YES,
        @"AnotherSetting": @1.f
    }];

    [preferences registerBool:&doThing default:NO forKey:@"DoThing"];

    NSLog(@"Am I enabled? %i", [preferences boolForKey:@"Enabled"]);
    NSLog(@"Can I do thing? %i", doThing);
}

References

Security

As of Cephei 1.12, HBPreferences restricts most Apple preferences (identifiers starting with com.apple.…) from being read/written from a sandboxed process. This protects against a malicious app using HBPreferences as a way to gather sensitive information or change system preferences without the user’s knowledge. For instance, an App Store app could phish for the user’s Apple ID login, creating a very real-looking login prompt by pre-filling their email address in the username box, or gain access to the numbers/email addresses of people the user has recently contacted.

There is currently no way to avoid this restriction while still using HBPreferences. If you need access to Apple preferences, design your code to not need to do this from within the sandbox. This could be done using IPC from an unsandboxed process such as SpringBoard. Avoid sending sensitive information via IPC to sandboxed apps, as they can still get access to data you send through various ways.

If this is an inconvenience for you and you believe an exception should be made, please file an issue to discuss it.

  • Creates an instance of the class for the specified identifier.

    Declaration

    Objective-C

    + (nonnull instancetype)preferencesForIdentifier:(nonnull NSString *)identifier;

    Swift

    convenience init(forIdentifier identifier: String)

    Parameters

    identifier

    The identifier to be used. This is usually the same as the package identifier of the tweak. @returns An autoreleased instance of HBPreferences for the specified identifier.

  • Initializes an instance of the class for the specified identifier.

    Declaration

    Objective-C

    - (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier;

    Swift

    init(identifier: String)

    Parameters

    identifier

    The identifier to be used. This is usually the same as the package identifier of the tweak. @returns An autoreleased instance of HBPreferences for the specified identifier.

  • The preferences identifier provided at initialisation.

    Declaration

    Objective-C

    @property (readonly, retain, nonatomic) NSString *_Nonnull identifier;

    Swift

    var identifier: String { get }
  • Synchronizes preferences data to prevent race conditions.

    On iOS 8.0 and later, waits until all communications between the cfprefsd daemon and the current process have completed, preventing race conditions and guaranteeing no data will be lost. Prior to iOS 8.0, writes all pending changes to disk, and reads latest preferences from disk.

    Do not use this method directly unless you have a specific need. HBPreferences will synchronize automatically when needed. For further information on what this method does and when to use it, refer to NSUserDefaults in Practice § “Sharing Defaults Between Programs”.

    @returns YES if synchronization was successful, NO if an error occurred.

    Declaration

    Objective-C

    - (BOOL)synchronize;

    Swift

    func synchronize() -> Bool
  • The default preferences to be used when no value has been set by the user.

    You may modify the values of this dictionary directly.

    Declaration

    Objective-C

    @property (readonly, copy, nonatomic)
        NSMutableDictionary<NSString *, id> *_Nonnull defaults;

    Swift

    @NSCopying var defaults: NSMutableDictionary { get }
  • Adds the contents of the specified dictionary to the defaults property.

    Merges the provided dictionary with the mutable dictionary found on the defaults property.

    See

    defaults

    Declaration

    Objective-C

    - (void)registerDefaults:(nonnull NSDictionary<NSString *, id> *)defaultValues;

    Swift

    func registerDefaults(_ defaultValues: [String : Any])

    Parameters

    defaultValues

    The dictionary of keys and values you want to register.

  • Returns a dictionary that contains all preferences that are set.

    This does not include default values.

    @returns A dictionary containing all keys and values.

    Declaration

    Objective-C

    - (nonnull NSDictionary<NSString *, id> *)dictionaryRepresentation;

    Swift

    func dictionaryRepresentation() -> [String : Any]
  • Returns the object associated with the specified key.

    If the preference is not yet set, returns the default. If no default is set, returns nil.

    Warning

    You must manually synchronize preferences or use registerObject:default:forKey: for this value to be updated when running on iOS 7 or older.

    Declaration

    Objective-C

    - (nonnull id)objectForKey:(nonnull NSString *)key;

    Swift

    func object(forKey key: String) -> Any

    Parameters

    key

    The key for which to return the corresponding value. @returns The object associated with the specified key.

  • Returns the integer value associated with the specified key.

    If the preference is not yet set, returns the default. If no default is set, returns nil.

    See

    objectForKey:

    Declaration

    Objective-C

    - (NSInteger)integerForKey:(nonnull NSString *)key;

    Swift

    func integer(forKey key: String) -> Int

    Parameters

    key

    The key for which to return the corresponding value. @returns The integer value associated with the specified key.

  • Returns the unsigned integer value associated with the specified key.

    If the preference is not yet set, returns the default. If no default is set, returns nil.

    See

    objectForKey:

    Declaration

    Objective-C

    - (NSUInteger)unsignedIntegerForKey:(nonnull NSString *)key;

    Swift

    func unsignedInteger(forKey key: String) -> UInt

    Parameters

    key

    The key for which to return the corresponding value. @returns The unsigned integer value associated with the specified key.

  • Returns the floating-point value associated with the specified key.

    If the preference is not yet set, returns the default. If no default is set, returns nil.

    See

    objectForKey:

    Declaration

    Objective-C

    - (CGFloat)floatForKey:(nonnull NSString *)key;

    Swift

    func float(forKey key: String) -> CGFloat

    Parameters

    key

    The key for which to return the corresponding value. @returns The floating-point value associated with the specified key.

  • Returns the double value associated with the specified key.

    If the preference is not yet set, returns the default. If no default is set, returns nil.

    See

    objectForKey:

    Declaration

    Objective-C

    - (double)doubleForKey:(nonnull NSString *)key;

    Swift

    func double(forKey key: String) -> Double

    Parameters

    key

    The key for which to return the corresponding value. @returns The double value associated with the specified key.

  • Returns the Boolean value associated with the specified key.

    If the preference is not yet set, returns the default. If no default is set, returns nil.

    See

    objectForKey:

    Declaration

    Objective-C

    - (BOOL)boolForKey:(nonnull NSString *)key;

    Swift

    func bool(forKey key: String) -> Bool

    Parameters

    key

    The key for which to return the corresponding value. @returns The Boolean value associated with the specified key.

  • Returns the value associated with a given key.

    This method behaves the same as objectForKey:.

    See

    objectForKey:

    Declaration

    Objective-C

    - (nonnull id)objectForKeyedSubscript:(nonnull id)key;

    Swift

    subscript(key: Any) -> Any! { get set }

    Parameters

    key

    The key for which to return the corresponding value. @returns The value associated with the specified key.

  • Returns the object associated with the specified key, or if no user preference is set, the provided default.

    Declaration

    Objective-C

    - (nonnull id)objectForKey:(nonnull NSString *)key
                       default:(nullable id)defaultValue;

    Swift

    func object(forKey key: String, default defaultValue: Any?) -> Any

    Parameters

    key

    The key for which to return the corresponding value.

    defaultValue

    The default value to use when no user preference is set. @returns The object associated with the specified key, or the default value.

  • Returns the integer value associated with the specified key, or if no user preference is set, the provided default.

    See

    objectForKey:default:

    Declaration

    Objective-C

    - (NSInteger)integerForKey:(nonnull NSString *)key
                       default:(NSInteger)defaultValue;

    Swift

    func integer(forKey key: String, default defaultValue: Int) -> Int

    Parameters

    key

    The key for which to return the corresponding value.

    defaultValue

    The default value to use when no user preference is set. @returns The integer value associated with the specified key, or the default value.

  • Returns the unsigned integer value associated with the specified key, or if no user preference is set, the provided default.

    See

    objectForKey:default:

    Declaration

    Objective-C

    - (NSUInteger)unsignedIntegerForKey:(nonnull NSString *)key
                                default:(NSUInteger)defaultValue;

    Swift

    func unsignedInteger(forKey key: String, default defaultValue: UInt) -> UInt

    Parameters

    key

    The key for which to return the corresponding value.

    defaultValue

    The default value to use when no user preference is set. @returns The unsigned integer value associated with the specified key, or the default value.

  • Returns the floating-point value associated with the specified key, or if no user preference is set, the provided default.

    See

    objectForKey:default:

    Declaration

    Objective-C

    - (CGFloat)floatForKey:(nonnull NSString *)key default:(CGFloat)defaultValue;

    Swift

    func float(forKey key: String, default defaultValue: CGFloat) -> CGFloat

    Parameters

    key

    The key for which to return the corresponding value.

    defaultValue

    The default value to use when no user preference is set. @returns The floating-point value associated with the specified key, or the default value.

  • Returns the double value associated with the specified key, or if no user preference is set, the provided default.

    See

    objectForKey:default:

    Declaration

    Objective-C

    - (double)doubleForKey:(nonnull NSString *)key default:(double)defaultValue;

    Swift

    func double(forKey key: String, default defaultValue: Double) -> Double

    Parameters

    key

    The key for which to return the corresponding value.

    defaultValue

    The default value to use when no user preference is set. @returns The double value associated with the specified key, or the default value.

  • Returns the Boolean value associated with the specified key, or if no user preference is set, the provided default.

    See

    objectForKey:default:

    Declaration

    Objective-C

    - (BOOL)boolForKey:(nonnull NSString *)key default:(BOOL)defaultValue;

    Swift

    func bool(forKey key: String, default defaultValue: Bool) -> Bool

    Parameters

    key

    The key for which to return the corresponding value.

    defaultValue

    The default value to use when no user preference is set. @returns The Boolean value associated with the specified key, or the default value.

  • Sets the value of the specified key.

    You should only call these methods if you are certain that the process is running as the mobile user.

    Declaration

    Objective-C

    - (void)setObject:(nullable id)value forKey:(nonnull NSString *)key;

    Swift

    func setObject(_ value: Any?, forKey key: String)

    Parameters

    value

    The object to store in the preferences.

    key

    The key with which to associate with the value. @exception HBPreferencesNotMobileException Thrown when the method is called by a process not running as the mobile user.

  • Sets the value of the specified key to the specified integer value.

    This is a convenience method that calls setObject:forKey:. See the discussion of that method for more details.

    See

    setObject:forKey:

    Declaration

    Objective-C

    - (void)setInteger:(NSInteger)value forKey:(nonnull NSString *)key;

    Swift

    func setInteger(_ value: Int, forKey key: String)

    Parameters

    value

    The integer value to store in the preferences.

    key

    The key with which to associate with the value.

  • Sets the value of the specified key to the specified unsigned integer value.

    This is a convenience method that calls setObject:forKey:. See the discussion of that method for more details.

    See

    setObject:forKey:

    Declaration

    Objective-C

    - (void)setUnsignedInteger:(NSUInteger)value forKey:(nonnull NSString *)key;

    Swift

    func setUnsignedInteger(_ value: UInt, forKey key: String)

    Parameters

    value

    The unsigned integer value to store in the preferences.

    key

    The key with which to associate with the value.

  • Sets the value of the specified key to the specified floating-point value.

    This is a convenience method that calls setObject:forKey:. See the discussion of that method for more details.

    See

    setObject:forKey:

    Declaration

    Objective-C

    - (void)setFloat:(CGFloat)value forKey:(nonnull NSString *)key;

    Swift

    func setFloat(_ value: CGFloat, forKey key: String)

    Parameters

    value

    The floating-point value to store in the preferences.

    key

    The key with which to associate with the value.

  • Sets the value of the specified key to the specified double value.

    This is a convenience method that calls setObject:forKey:. See the discussion of that method for more details.

    See

    setObject:forKey:

    Declaration

    Objective-C

    - (void)setDouble:(double)value forKey:(nonnull NSString *)key;

    Swift

    func setDouble(_ value: Double, forKey key: String)

    Parameters

    value

    The double value to store in the preferences.

    key

    The key with which to associate with the value.

  • Sets the value of the specified key to the specified Boolean value.

    This is a convenience method that calls setObject:forKey:. See the discussion of that method for more details.

    See

    setObject:forKey:

    Declaration

    Objective-C

    - (void)setBool:(BOOL)value forKey:(nonnull NSString *)key;

    Swift

    func setBool(_ value: Bool, forKey key: String)

    Parameters

    value

    The Boolean value to store in the preferences.

    key

    The key with which to associate with the value.

  • Sets the value of the specified key to the specified value.

    Declaration

    Objective-C

    - (void)setObject:(nullable id)object forKeyedSubscript:(nonnull id)key;

    Parameters

    object

    The value to store in the preferences.

    key

    The key with which to associate with the value.

  • Removes a given key and its associated value from the dictionary.

    Blocks are called after HBPreferences’ cache of values is updated. The block will also be called immediately after calling this method. See registerObject:default:forKey: for details on how to set up callbacks.

    Declaration

    Objective-C

    - (void)removeObjectForKey:(nonnull NSString *)key;

    Swift

    func removeObject(forKey key: String)

    Parameters

    key

    The key to remove.

  • Removes all stored preferences.

    This method acts in the same way as discussed in removeObjectForKey:.

    Declaration

    Objective-C

    - (void)removeAllObjects;

    Swift

    func removeAllObjects()
  • Register an object to be automatically set to the user’s preference.

    If the preference is not yet set, the object will be set to the provided default.

    You must post a Darwin notification after updating preferences for this to work. In particular, it must be set to the value of identifier, followed by /ReloadPrefs - for instance, ws.hbang.common.demo/ReloadPrefs. In a Preferences specifier property list, you can use the PostNotification key on your specifiers to achieve this:

    PostNotification ws.hbang.common.demo/ReloadPrefs

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerObject:(id _Nullable *_Nonnull)object
                   default:(nullable id)defaultValue
                    forKey:(nonnull NSString *)key;

    Swift

    func register(_ object: UnsafeMutablePointer<AnyObject?>, default defaultValue: Any?, forKey key: String)

    Parameters

    object

    The pointer to the object.

    defaultValue

    The default value to be used if no user preference is set.

    key

    The key in the preferences property list.

  • Register an integer value to be automatically set to the user’s preference.

    If the preference is not yet set, the object will be set to the provided default.

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerInteger:(nonnull NSInteger *)object
                    default:(NSInteger)defaultValue
                     forKey:(nonnull NSString *)key;

    Swift

    func register(_ object: UnsafeMutablePointer<Int>, default defaultValue: Int, forKey key: String)

    Parameters

    object

    The pointer to the integer.

    defaultValue

    The default value to be used if no user preference is set.

    key

    The key in the preferences property list.

  • Register an unsigned integer value to be automatically set to the user’s preference.

    If the preference is not yet set, the object will be set to the provided default.

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerUnsignedInteger:(nonnull NSUInteger *)object
                            default:(NSUInteger)defaultValue
                             forKey:(nonnull NSString *)key;

    Swift

    func registerUnsignedInteger(_ object: UnsafeMutablePointer<UInt>, default defaultValue: UInt, forKey key: String)

    Parameters

    object

    The pointer to the unsigned integer.

    defaultValue

    The default value to be used if no user preference is set.

    key

    The key in the preferences property list.

  • Register a floating-point value to be automatically set to the user’s preference.

    If the preference is not yet set, the object will be set to the provided default.

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerFloat:(nonnull CGFloat *)object
                  default:(CGFloat)defaultValue
                   forKey:(nonnull NSString *)key;

    Swift

    func register(_ object: UnsafeMutablePointer<CGFloat>, default defaultValue: CGFloat, forKey key: String)

    Parameters

    object

    The pointer to the integer.

    defaultValue

    The default value to be used if no user preference is set.

    key

    The key in the preferences property list.

  • Register a double value to be automatically set to the user’s preference.

    If the preference is not yet set, the object will be set to the provided default.

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerDouble:(nonnull double *)object
                   default:(double)defaultValue
                    forKey:(nonnull NSString *)key;

    Swift

    func register(_ object: UnsafeMutablePointer<Double>, default defaultValue: Double, forKey key: String)

    Parameters

    object

    The pointer to the double.

    defaultValue

    The default value to be used if no user preference is set.

    key

    The key in the preferences property list.

  • Register a Boolean value to be automatically set to the user’s preference.

    If the preference is not yet set, the object will be set to the provided default.

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerBool:(nonnull BOOL *)object
                 default:(BOOL)defaultValue
                  forKey:(nonnull NSString *)key;

    Swift

    func register(_ object: UnsafeMutablePointer<ObjCBool>, default defaultValue: Bool, forKey key: String)

    Parameters

    object

    The pointer to the Boolean.

    defaultValue

    The default value to be used if no user preference is set.

    key

    The key in the preferences property list.

  • Register a block to be called when a preference change is detected.

    Blocks are called after HBPreferences’ cache of values is updated. The block will also be called immediately after calling this method. See registerObject:default:forKey: for details on how to set up callbacks.

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerPreferenceChangeBlock:
        (nonnull HBPreferencesChangeCallback)callback;

    Swift

    func registerPreferenceChange(_ callback: @escaping HBPreferencesChangeCallback)

    Parameters

    callback

    A block object called when the specified key’s value changes. The block object takes no parameters and returns no value.

  • Register a block to be called when a specific preference is changed.

    Blocks are called after HBPreferences’ cache of values is updated. The block will also be called immediately after calling this method. See registerObject:default:forKey: for details on how to set up callbacks.

    See

    registerObject:default:forKey:

    Declaration

    Objective-C

    - (void)registerPreferenceChangeBlock:
                (nonnull HBPreferencesValueChangeCallback)callback
                                   forKey:(nonnull NSString *)key;

    Swift

    func registerPreferenceChange(_ callback: @escaping HBPreferencesValueChangeCallback, forKey key: String)

    Parameters

    callback

    A block object called when the specified key’s value changes. The block object’s parameters are the key and its new value.

    key

    The key to listen for.