当前位置:  开发笔记 > IOS > 正文

即使您未打开"设置应用",也可以在Settings.bundle默认设置中进行设置

如何解决《即使您未打开"设置应用",也可以在Settings.bundle默认设置中进行设置》经验,为你挑选了4个好方法。

我有一个带有settings.bundle的iPhone应用程序,可以处理我的应用程序的各种设置.我可以在root.plist文件中设置默认值(使用DefaultValue属性),但这些只在用户第一次打开设置应用程序时使用.有没有办法在您的应用程序安装时写出这些值?我知道我可以编写代码来检查我的应用程序的第一次启动,然后将它们写出来,但之后它们位于两个不同的地方.

以下是我的root.plist中的一个条目作为示例:


    Type
    PSToggleSwitchSpecifier
    Title
    Open To Top Location
    Key
    open_top_location
    DefaultValue
    YES
    TrueValue
    YES
    FalseValue
    NO

最终的结果应该是,如果我要求'open_to_top_location',我会得到一个YES,而不是在用户第一次打开Settings应用程序之前根本不存在.

有任何想法吗?



1> PCheese..:

如果我理解正确,你想避免两次指定默认值(一次是在Settings.bundle/Root.plist文件中的"DefaultValue"键,一次是在你的app初始化代码中),所以你不必保留它们同步.

由于Settings.bundle存储在应用程序包本身中,因此您只需读取其中给出的默认值即可.我整理了一些查看"设置"包的示例代码,并为每个键读取默认值.请注意,这不会写出默认密钥; 如果它们不存在,您需要在每次启动时阅读并注册它们(随意更改).我只做了一些粗略的测试,所以确保它在所有情况下都适合你.

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    NSString *name = [[NSUserDefaults standardUserDefaults] stringForKey:@"name"];
    NSLog(@"name before is %@", name);

    // Note: this will not work for boolean values as noted by bpapa below.
    // If you use booleans, you should use objectForKey above and check for null
    if(!name) {
        [self registerDefaultsFromSettingsBundle];
        name = [[NSUserDefaults standardUserDefaults] stringForKey:@"name"];
    }
    NSLog(@"name after is %@", name);
}

- (void)registerDefaultsFromSettingsBundle {
    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 && [[prefSpecification allKeys] containsObject:@"DefaultValue"]) {
            [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
        }
    }

    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
    [defaultsToRegister release];
}


有一点需要注意这个解决方案 - 如果你的默认值是一个布尔值,它就不起作用,因为如果默认设置为NO或者它不存在,"if(!name)"返回NO.为了解决这个问题,我使用objectForKey,因为它将返回0,1或null.
值得注意的是,`registerDefaultsFromSettingsBundle`不需要限制为条件执行:它可以安全地一直运行,因为`registerDefaults`永远不会覆盖现有的设置; 它仅为没有值的设置提供默认值.但是,避免冗余执行可以节省(微小)时间.
我希望有一些神奇的捆绑设置,我错过了像"WriteDefaultsOnInstall",但如果没有,这将做,谢谢:)
我必须注意,这些东西不适用于本地化的应用程序:它打开`[settingsBundle stringByAppendingPathComponent:@"Root.plist"]]`,而对于本地化的应用程序,你需要`localeid.lproj/Root.plist`.第二,`[defaultsToRegister setObject:...]`引发了nil值的异常.

2> Lawrence Joh..:

这是我的代码基于@ PCheese的答案,它增加了对没有默认值和子窗格的键的支持.

- (void)registerDefaultsFromSettingsBundle {
    [[NSUserDefaults standardUserDefaults] registerDefaults:[self defaultsFromPlistNamed:@"Root"]];
}

- (NSDictionary *)defaultsFromPlistNamed:(NSString *)plistName {
    NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    NSAssert(settingsBundle, @"Could not find Settings.bundle while loading defaults.");

    NSString *plistFullName = [NSString stringWithFormat:@"%@.plist", plistName];

    NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:plistFullName]];
    NSAssert1(settings, @"Could not load plist '%@' while loading defaults.", plistFullName);

    NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
    NSAssert1(preferences, @"Could not find preferences entry in plist '%@' while loading defaults.", plistFullName);

    NSMutableDictionary *defaults = [NSMutableDictionary dictionary];
    for(NSDictionary *prefSpecification in preferences) {
        NSString *key = [prefSpecification objectForKey:@"Key"];
        id value = [prefSpecification objectForKey:@"DefaultValue"];
        if(key && value) {
            [defaults setObject:value forKey:key];
        } 

        NSString *type = [prefSpecification objectForKey:@"Type"];
        if ([type isEqualToString:@"PSChildPaneSpecifier"]) {
            NSString *file = [prefSpecification objectForKey:@"File"];
            NSAssert1(file, @"Unable to get child plist name from plist '%@'", plistFullName);
            [defaults addEntriesFromDictionary:[self defaultsFromPlistNamed:file]];
        }        
    }

    return defaults;
}



3> 小智..:

这是Swift版本:从以下地址调用:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    self.registerDefaultsFromSettingsBundle()

    return true
}

转换功能:

func registerDefaultsFromSettingsBundle(){
    //NSLog("Registering default values from Settings.bundle");
    let defs: NSUserDefaults = NSUserDefaults.standardUserDefaults()
    defs.synchronize()

    var settingsBundle: NSString = NSBundle.mainBundle().pathForResource("Settings", ofType: "bundle")!    
    if(settingsBundle.containsString("")){
        NSLog("Could not find Settings.bundle");
        return;
    }
    var settings: NSDictionary = NSDictionary(contentsOfFile: settingsBundle.stringByAppendingPathComponent("Root.plist"))!
    var preferences: NSArray = settings.objectForKey("PreferenceSpecifiers") as NSArray
    var defaultsToRegister: NSMutableDictionary = NSMutableDictionary(capacity: preferences.count)

    for prefSpecification in preferences {
        if (prefSpecification.objectForKey("Key") != nil) {
            let key: NSString = prefSpecification.objectForKey("Key")! as NSString
            if !key.containsString("") {
                let currentObject: AnyObject? = defs.objectForKey(key)
                if currentObject == nil {
                    // not readable: set value from Settings.bundle
                    let objectToSet: AnyObject? = prefSpecification.objectForKey("DefaultValue")
                    defaultsToRegister.setObject(objectToSet!, forKey: key)
                    NSLog("Setting object \(objectToSet) for key \(key)")
                }else{
                    //already readable: don't touch
                    //NSLog("Key \(key) is readable (value: \(currentObject)), nothing written to defaults.");
                }
            }
        }
    }
    defs.registerDefaults(defaultsToRegister)
    defs.synchronize()
}



4> Anders Cedro..:

Swift 3版本

    func registerDefaultsFromSettingsBundle(){
    guard let settingsBundle = Bundle.main.path(forResource: "Settings", ofType: "bundle") else {
        print("Could not locate Settings.bundle")
        return
    }

    guard let settings = NSDictionary(contentsOfFile: settingsBundle+"/Root.plist") else {
        print("Could not read Root.plist")
        return
    }

    let preferences = settings["PreferenceSpecifiers"] as! NSArray
    var defaultsToRegister = [String: AnyObject]()
    for prefSpecification in preferences {
        if let post = prefSpecification as? [String: AnyObject] {
            guard let key = post["Key"] as? String,
                let defaultValue = post["DefaultValue"] else {
                    continue
            }
            defaultsToRegister[key] = defaultValue
        }
    }
    UserDefaults.standard.register(defaults: defaultsToRegister)
}

推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有