Czy możesz dokonać ustawień w Ustawieniach.pakiet domyślny, nawet jeśli nie otworzysz aplikacji Ustawienia

Mam aplikację na iPhone ' a z ustawieniami.pakiet, który obsługuje różne ustawienia dla mojej aplikacji. Mogę ustawić domyślne wartości w moim katalogu głównym.plik plist (przy użyciu właściwości DefaultValue), ale są one używane tylko przy pierwszym otwarciu aplikacji ustawienia. Czy istnieje sposób na zapisanie tych wartości podczas instalacji aplikacji? Wiem, że mogę po prostu napisać kod, który sprawdza się przy pierwszym uruchomieniu mojej aplikacji, a następnie napisać je, ale wtedy są one w dwóch różnych miejsca.

Oto wpis z mojego korzenia.plist jako przykład:

<dict>
    <key>Type</key>
    <string>PSToggleSwitchSpecifier</string>
    <key>Title</key>
    <string>Open To Top Location</string>
    <key>Key</key>
    <string>open_top_location</string>
    <key>DefaultValue</key>
    <string>YES</string>
    <key>TrueValue</key>
    <string>YES</string>
    <key>FalseValue</key>
    <string>NO</string>
</dict>

Końcowy wynik powinien być taki, że jeśli Poproszę o 'open_to_top_location', otrzymuję odpowiedź "Tak", zamiast tego, że nie ma go w ogóle, dopóki użytkownik nie otworzy aplikacji ustawień.

Jakieś pomysły?
Author: rustyshelf, 2009-02-04

8 answers

Jeśli dobrze Cię zrozumiałem, chcesz uniknąć dwukrotnego podawania wartości domyślnych (raz jako "DefaultValue" w Ustawieniach.bundle / Root.plist, a raz w kodzie inicjalizacji aplikacji), dzięki czemu nie musisz ich synchronizować.

Od Ustawienia.Pakiet jest przechowywany w samym pakiecie aplikacji, możesz po prostu odczytać podane tam wartości domyślne. Zebrałem przykładowy kod, który patrzy na pakiet ustawień i odczytuje domyślne wartości dla każdego klucza. Zauważ, że to nie zapisuje kluczy domyślnych; jeśli nie istnieją, musisz je przeczytać i zarejestrować przy każdym uruchomieniu(możesz to zmienić). Zrobiłem tylko kilka pobieżnych testów, więc upewnij się, że działa dla Ciebie we wszystkich przypadkach.

- (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];
}
 94
Author: PCheese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-17 00:40:48

Oto Mój kod oparty na odpowiedzi @PCheese , która dodaje obsługę kluczy bez wartości domyślnej i okien potomnych.

- (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;
}
 12
Author: Lawrence Johnston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:00:35

Oto wersja Swift: call it from:

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

    return true
}

Przekształcona Funkcja:

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()
}
 9
Author: yanko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-14 17:39:32

Wersja 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)
}
 5
Author: Anders Cedronius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-21 09:36:05

A Swift 2 compatible version

func registerDefaultsFromSettingsBundle(){

    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.synchronize()

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

    for prefSpecification in preferences {
        if (prefSpecification.objectForKey("Key") != nil) {
            let key = prefSpecification.objectForKey("Key")! as! String
            if !key.containsString("") {
                let currentObject = defaults.objectForKey(key)
                if currentObject == nil {
                    // not readable: set value from Settings.bundle
                    let objectToSet = prefSpecification.objectForKey("DefaultValue")
                    defaultsToRegister[key] = objectToSet!
                    NSLog("Setting object \(objectToSet) for key \(key)")
                }
            }
        }
    }
    defaults.registerDefaults(defaultsToRegister)
    defaults.synchronize()
}
 3
Author: JTango18,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 05:56:19

Jeszcze jedna wersja tego samego tematu. Zachowałem wsparcie Lawrence ' a Johnstona dla szyb dziecięcych i dodałem wsparcie i18n/l10n.

// This code is folklore, first created by an unknown person and copied, pasted
// and published by many different programmers, each (hopefully) of whom added
// some improvemrnts. (c) the People of the Earth
- (NSDictionary *)defaultsFromPlistNamed:(NSString *)plistName {
    NSString *settingsBundlePath = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    if (!settingsBundlePath) {
        NSAssert(settingsBundlePath, @"Could not find Settings.bundle while loading defaults.");
        return nil;
    }

    NSBundle *settingsBundle = [NSBundle bundleWithPath:settingsBundlePath];
    if (!settingsBundlePath) {
        NSAssert(settingsBundle, @"Could not load Settings.bundle while loading defaults.");
        return nil;
    }

    NSString *plistFullName = [settingsBundle pathForResource:plistName ofType:@"plist"];
    if (!plistName) {
        NSAssert1(settings, @"Could not find plist '%@' while loading defaults.", plistFullName);
        return nil;
    }

    NSDictionary *settings_dic = [NSDictionary dictionaryWithContentsOfFile:plistFullName];
    if (!settings_dic) {
        NSAssert1(settings_dic, @"Could not load plist '%@' while loading defaults.", plistFullName);
        return nil;
    }

    NSArray *preferences = [settings_dic 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"];
        if (key) {
            id value = [prefSpecification objectForKey:@"DefaultValue"];
            if(value) {
                [defaults setObject:value forKey:key];
                NSLog(@"setting %@ = %@",key,value);
            } 
        }

        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);
            if (file) {
                [defaults addEntriesFromDictionary:[self defaultsFromPlistNamed:file]];
            }
        }        
    }

    return defaults;
}

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

Wywołaj [self registerDefaultsFromSettingsBundle]; z - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

if(x) {NSAssert(x);return nil;} wygląda głupio, ale czuję się leniwy, żeby coś z tym zrobić.

 0
Author: 18446744073709551615,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-23 11:46:40

Inne podejście: generowanie kodu

Poniższy plik generuje Objective-C z pojedynczą funkcją, która rejestruje domyślne wartości dla roota.plist.

xsltproc settings.xslt Settings.bundle/Root.plist > registerDefaults.m

In może być uruchamiany automatycznie za pomocą fazy budowania "Run Script" w XCode. Faza powinna być umieszczona przed "kompilacją źródeł". (xsltproc pochodzi z OS X.)

"Uruchom skrypt" zrzut ekranu

Jest to dość proste i nie obsługuje zagnieżdżonych plików, ale może ktoś ma zastosowanie do to.

Ustawienia.xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8" omit-xml-declaration="yes" indent="no" />

  <xsl:template match="dict">
    <xsl:choose>
      <xsl:when test="key[.='DefaultValue']/following-sibling::*[position()=1 and self::true]">
        @"YES",
      </xsl:when>
      <xsl:when test="key[.='DefaultValue']/following-sibling::*[position()=1 and self::false]">
        @"NO",
      </xsl:when>
      <xsl:otherwise>
        @"<xsl:value-of select="key[.='DefaultValue']/following-sibling::*[1]"/>",
      </xsl:otherwise>
    </xsl:choose>
    @"<xsl:value-of select="key[.='Key']/following-sibling::*[1]"/>",
  </xsl:template>

  <xsl:template match="/">
    void registerDefaults() {

    NSDictionary *defaults =
    [NSDictionary dictionaryWithObjectsAndKeys:
    <xsl:apply-templates select="descendant::key[.='DefaultValue']/.."/>
    nil];

    [[NSUserDefaults standardUserDefaults] registerDefaults: defaults];
    }
  </xsl:template>

</xsl:stylesheet>

Jest oparty na pracyBenjamin Ragheb .

 0
Author: nschum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-01 21:55:28

Znacznie czystsza wersja swift 2.2, wymaga szybkiego rozszerzenia na string do przywrócenia stringByAppendingPathComponent:

extension String {
    func stringByAppendingPathComponent(path: String) -> String {
        let nsSt = self as NSString
        return nsSt.stringByAppendingPathComponent(path)
    }
}

func registerDefaultsFromSettingsBundle() {
    guard let settingsBundle = NSBundle.mainBundle().pathForResource("Settings", ofType: "bundle") else {
        log.debug("Could not find Settings.bundle")
        return
    }

    let settings = NSDictionary(contentsOfFile: settingsBundle.stringByAppendingPathComponent("Root.plist"))!

    let preferences = settings["PreferenceSpecifiers"] as! NSArray

    var defaultsToRegister = [String: AnyObject]()

    for prefSpecification in preferences {
        guard let key = prefSpecification["Key"] as? String,
        let defaultValue = prefSpecification["DefaultValue"] else {
            continue
        }

        defaultsToRegister[key] = defaultValue
    }
    NSUserDefaults.standardUserDefaults().registerDefaults(defaultsToRegister)
}
 0
Author: JuJoDi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-07 11:57:13