How to retrieve values from settings.bundle in Objective-c/Swift?

后端 未结 6 512
独厮守ぢ
独厮守ぢ 2020-12-08 07:52

I have created a project that set and retrieve values from settings.bundle. I have also set some defaults values in settings.bundle file. Now the problem i

相关标签:
6条回答
  • 2020-12-08 08:14

    Although you define the defaults settings, they are not really stored as a value. They are stored as default. If you try to read it, the value is null. Default setting is another property as value is. But it doesnt mean that will write the default value as a default.

    What I do is, first, check if some setting,(that I'm sure that should have a value) has anything stored on it. If it doesn't have anything then I write all the defaults.

    Here is an example.

    on AppDelegate.m I check if email_notificaciones_preference has a value, if not, I write ALL default settings to each setting.

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
        NSUserDefaults * standardUserDefaults = [NSUserDefaults standardUserDefaults];
        NSString * email_notificaciones_preference = [standardUserDefaults objectForKey:@"email_notificaciones_preference"];
        if (!email_notificaciones_preference) {
            [self registerDefaultsFromSettingsBundle];
        }
    
    }
    

    This function is what I use to write defaults to each element.

    #pragma NSUserDefaults
    - (void)registerDefaultsFromSettingsBundle {
        // this function writes default settings as settings
        NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
        if(!settingsBundle) {
            NSLog(@"Could not find Settings.bundle");
            return;
        }
    
        NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
        NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
    
        NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
        for(NSDictionary *prefSpecification in preferences) {
            NSString *key = [prefSpecification objectForKey:@"Key"];
            if(key) {
                [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
                NSLog(@"writing as default %@ to the key %@",[prefSpecification objectForKey:@"DefaultValue"],key);
            }
        }
    
        [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
    
    }
    

    Hope that helps.

    0 讨论(0)
  • 2020-12-08 08:18

    try this

    To register Default Values of Setting bundles

    NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:defaultValue forKey:@"key"];
     [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
    

    Before retrieving setting bundles values synchronize data

    [[NSUserDefaults standardUserDefaults] synchronize]
    
    0 讨论(0)
  • 2020-12-08 08:26

    Updated for Swift 3:

    func registerDefaultsFromSettingsBundle() {
    
        let userDefaults = UserDefaults.standard
    
        if let settingsURL = Bundle.main.url(forResource: "Root", withExtension: "plist", subdirectory: "Settings.bundle"),
            let settings = NSDictionary(contentsOf: settingsURL),
            let preferences = settings["PreferenceSpecifiers"] as? [NSDictionary] {
    
            var defaultsToRegister = [String: AnyObject]()
            for prefSpecification in preferences {
                if let key = prefSpecification["Key"] as? String,
                    let value = prefSpecification["DefaultValue"] {
    
                    defaultsToRegister[key] = value as AnyObject
                    debugPrint("registerDefaultsFromSettingsBundle: (\(key), \(value)) \(type(of: value))")
                }
            }
    
            userDefaults.register(defaults: defaultsToRegister)
    
        } else {
            debugPrint("registerDefaultsFromSettingsBundle: Could not find Settings.bundle")
        }
    }
    
    0 讨论(0)
  • 2020-12-08 08:27

    Updated version for swift 2.1:

     func registerDefaultsFromSettingsBundle() {
        let userDefaults = NSUserDefaults.standardUserDefaults()
    
        if let settingsURL = NSBundle.mainBundle().URLForResource("Root", withExtension: "plist", subdirectory: "Settings.bundle"),
               settings = NSDictionary(contentsOfURL: settingsURL),
               preferences = settings["PreferenceSpecifiers"] as? [NSDictionary] {
    
            var defaultsToRegister = [String: AnyObject]()
            for prefSpecification in preferences {
                if let key = prefSpecification["Key"] as? String,
                       value = prefSpecification["DefaultValue"] {
    
                    defaultsToRegister[key] = value
                    NSLog("registerDefaultsFromSettingsBundle: (\(key), \(value)) \(value.dynamicType)")
                }
            }
    
            userDefaults.registerDefaults(defaultsToRegister);
        } else {
            NSLog("registerDefaultsFromSettingsBundle: Could not find Settings.bundle");
        }
    }
    
    0 讨论(0)
  • 2020-12-08 08:34

    You can use a simple property wrapper like this:

    Usage

    @SettingsBundleStorage(key: "storageUsage_preference")
    var storageUsage: Double
    

    Note that this is 100% objective-c compatible by just adding @objc before the variable.


    Implementation of the code behind this:

    Settings bundle values are live in the UserDefaults so you can use a custom PropertyWrapper for it. The following wrapper will work for any UserDefault value, including all values of the SettingsBundle.

    Property wrapper

    @propertyWrapper
    public struct SettingsBundleStorage<T> {    
        private let key: String
    
        public init(key: String) {
            self.key = key
            setBundleDefaults(plist: .root) // This is the main plist
            setBundleDefaults(plist: .child(name: "DeveloperOptions")) // This is an example child.
        }
    
        public var wrappedValue: T {
            get { UserDefaults.standard.value(forKey: key) as! T }
            set { UserDefaults.standard.set(newValue, forKey: key) }
        }
    }
    

    The root and the children

    You should pass the following enum for the root and the child plists:

    extension SettingsBundleStorage {
    
        enum PList {
            case root
            case child(name: String)
    
            var name: String {
                var file: String
                switch self {
                case .root: file = "Root"
                case .child(let name): file = name.replacingOccurrences(of: ".plist", with: "")
                }
                file.append(".plist")
                return file
            }
        }
    }
    

    Find and set defaults if needed.

    This wrapper finds the default value of the bundle keys with this function:

    extension SettingsBundleStorage {
    
        func setBundleDefaults(plist: PList = .root) {
            let settingsName                    = "Settings"
            let settingsExtension               = "bundle"
            let settingsPreferencesItems        = "PreferenceSpecifiers"
            let settingsPreferenceKey           = "Key"
            let settingsPreferenceDefaultValue  = "DefaultValue"
    
            guard let settingsBundleURL = Bundle.main.url(forResource: settingsName, withExtension: settingsExtension),
                  let settingsData = try? Data(contentsOf: settingsBundleURL.appendingPathComponent(plist.name)),
                  let settingsPlist = try? PropertyListSerialization.propertyList(
                    from: settingsData,
                    options: [],
                    format: nil) as? [String: Any],
                  let settingsPreferences = settingsPlist?[settingsPreferencesItems] as? [[String: Any]] else {
                return assertionFailure("Can not get the \(plist.name) from the bundle: \(settingsName)")
            }
    
            var defaultsToRegister = [String: Any]()
    
            settingsPreferences.forEach { preference in
                if let key = preference[settingsPreferenceKey] as? String {
                    defaultsToRegister[key] = preference[settingsPreferenceDefaultValue]
                }
            }
    
            UserDefaults.standard.register(defaults: defaultsToRegister)
        }
    }
    

    This wrapper can store/restore any kind of codable into/from the user defaults including all Swift standard data types that are already conformed to the codable.


    Also, you can find a similar but with way less code version for accessing any key-value from any user default, you can take a look at this answer here

    0 讨论(0)
  • 2020-12-08 08:40

    If anyone needs it - I translated the answer from MIQUEL to Swift (as good as I could as I'm still learning) :

    var standardUserDefaults = NSUserDefaults.standardUserDefaults()
    var us: AnyObject? = standardUserDefaults.objectForKey("your_preference")
    if us==nil {
        self.registerDefaultsFromSettingsBundle();
    }
    

    And the func registerDefaultsFromSettingsBundle:

    func registerDefaultsFromSettingsBundle() {
        // this function writes default settings as settings
        var settingsBundle = NSBundle.mainBundle().pathForResource("Settings", ofType: "bundle")
        if settingsBundle == nil {
            NSLog("Could not find Settings.bundle");
            return
        }
        var settings = NSDictionary(contentsOfFile:settingsBundle!.stringByAppendingPathComponent("Root.plist"))!
        var preferences: [NSDictionary] = settings.objectForKey("PreferenceSpecifiers") as [NSDictionary];
        var defaultsToRegister = NSMutableDictionary(capacity:(preferences.count));
    
        for prefSpecification:NSDictionary in preferences {
            var key: NSCopying? = prefSpecification.objectForKey("Key") as NSCopying?
            if key != nil {
                defaultsToRegister.setObject(prefSpecification.objectForKey("DefaultValue")!, forKey: key!)
            }
        }
        NSUserDefaults.standardUserDefaults().registerDefaults(defaultsToRegister);  
    }
    
    0 讨论(0)
提交回复
热议问题