Skip to content

Instantly share code, notes, and snippets.

@donato-fiore
Last active May 12, 2025 23:11
Show Gist options
  • Save donato-fiore/e30b97bd083e0b9b458d08a7d870049b to your computer and use it in GitHub Desktop.
Save donato-fiore/e30b97bd083e0b9b458d08a7d870049b to your computer and use it in GitHub Desktop.
PSListController extension to load JSON files.
#include <Preferences/PSListController.h>
@interface PSListController (JSON)
- (NSMutableArray *)loadSpecifiersFromJSONName:(NSString *)name target:(PSListController *)target;
- (NSMutableArray *)loadSpecifiersFromJSONName:(NSString *)name target:(PSListController *)target bundle:(NSBundle *)bundle;
@end
#include "PSListController+JSON.h"
#include <dlfcn.h>
typedef NSArray *(*SpecifiersFromPlistType)(NSDictionary *plist, PSSpecifier *prevSpec, id target, NSString *plistName, NSBundle *curBundle, NSString **pTitle, NSString **pSpecifierID, PSListController *controller, NSMutableArray **pBundleControllers);
static SpecifiersFromPlistType SpecifiersFromPlist;
@implementation PSListController (JSON)
- (NSMutableArray *)loadSpecifiersFromJSONName:(NSString *)name target:(PSListController *)target {
return [self loadSpecifiersFromJSONName:name target:target bundle:[NSBundle bundleForClass:[target class]]];
}
- (NSMutableArray *)loadSpecifiersFromJSONName:(NSString *)name target:(PSListController *)target bundle:(NSBundle *)bundle {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
void *preferences = dlopen("/System/Library/PrivateFrameworks/Preferences.framework/Preferences", RTLD_LAZY);
SpecifiersFromPlist = (SpecifiersFromPlistType)dlsym(preferences, "SpecifiersFromPlist");
});
NSString *path = [bundle pathForResource:name ofType:@"json"];
if (!path) {
NSLog(@"Warning: failed to load preference json '%@.json' for bundle %@", name, bundle);
}
NSData *data = [NSData dataWithContentsOfFile:path];
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error) {
NSLog(@"Error: failed to parse preference json '%@.json' for bundle %@: %@", name, bundle, error);
return nil;
}
NSString *specifierID;
NSString *_title;
NSArray *bundleControllers = [self valueForKey:@"_bundleControllers"];
NSArray *result = SpecifiersFromPlist(json, self->_specifier, target, name, bundle,
&_title, &specifierID, self, &bundleControllers);
self.specifierID = specifierID;
self.title = _title;
return [result mutableCopy];
}
@end
{
"items": [
{
"cell": "PSGroupCell",
"label": "JSON Test First Page"
},
{
"cell": "PSSwitchCell",
"default": true,
"defaults": "com.yourcompany.jsontest",
"key": "AwesomeSwitch1",
"label": "Awesome Switch 1"
}
],
"title": "JSON Test"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment