operador opcion ingles idioma español descargar como cambiar aparece ajustes iphone cocoa-touch

opcion - descargar ajustes de operador iphone



¿Puede establecer la configuración en Settings.bundle por defecto incluso si no abre la aplicación de configuración (8)

Tengo una aplicación de iPhone con un conjunto de configuraciones que maneja varias configuraciones para mi aplicación. Puedo establecer valores predeterminados en mi archivo root.plist (usando la propiedad DefaultValue), pero estos solo se usan la primera vez que el usuario abre la aplicación de configuración. ¿Hay alguna forma de obtener estos valores por escrito cuando se instala su aplicación? Sé que puedo escribir un código que compruebe el primer lanzamiento de mi aplicación y luego escribirlos, pero luego están en dos lugares diferentes.

Aquí hay una entrada de mi root.plist como ejemplo:

<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>

El resultado final debería ser que si pido ''open_to_top_location'' obtengo un SÍ, en lugar de que no esté allí hasta la primera vez que el usuario abre la aplicación de Configuración.

¿Algunas ideas?


Aquí está la versión de Swift: llámala desde:

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

función convertida:

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() }


Aquí está mi código basado en la answer @ PCheese, que agrega compatibilidad para claves sin un valor predeterminado y paneles secundarios.

- (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; }


Si te entendí correctamente, quieres evitar que los valores predeterminados se especifiquen dos veces (una como "DefaultValue" en el archivo Settings.bundle / Root.plist, y una vez en el código de inicialización de la aplicación) para que no tengas que guardarlos en sincronizar

Como Settings.bundle se almacena dentro del paquete de la aplicación, puede leer los valores predeterminados allí. Puse un código de muestra que mira el paquete Configuraciones y lee los valores predeterminados para cada tecla allí. Tenga en cuenta que esto no escribe las claves predeterminadas; si no existen, tendrá que leerlos y registrarlos en cada lanzamiento (no dude en cambiar esto). Solo hice algunas pruebas superficiales, así que asegúrese de que funcione para usted en todos los casos.

- (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]; }


Swift 3 versión

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) }


Un enfoque diferente: generación de código

A continuación, se genera un archivo Objective-C con una única función que registra los valores predeterminados para Root.plist.

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

En se puede ejecutar automáticamente usando una fase de compilación "Ejecutar script" en XCode. La fase debe colocarse antes de "Compilar fuentes". (xsltproc viene con OS X.)

Esto es algo básico y no maneja archivos anidados, pero tal vez alguien tenga un uso para él.

settings.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>

El está basado en el trabajo de Benjamin Ragheb .


Una versión 2.2 mucho más limpia y rápida, requiere una extensión rápida en la cadena para restaurar 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) }


Una versión compatible con Swift 2

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() }


Una versión más del mismo tema. Mantuve el soporte de Lawrence Johnston para los paneles secundarios y agregué el soporte 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"]]; }

Llamar [self registerDefaultsFromSettingsBundle]; desde - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

if(x) {NSAssert(x);return nil;} parece estúpido, pero me siento flojo por hacer algo al respecto.