2011-07-21 17 views
8

He estado usando este sitio de forma pasiva durante algún tiempo y he leído las preguntas frecuentes, así que espero poder mantenerlas al mínimo.No se han podido leer los valores de Settings.bundle

Tengo una pregunta acerca de los archivos Settings.bundle en Objective-C. He estado usando las siguientes guías para poner en práctica uno de los:

  • How to create an iPhone preferences file
  • iOS Application Programming Guide - Implementing Application Preferences
  • estoy usando tanto Xcode 4.1 y la última Xcode 3. He utilizado la versión 3 para crear the Settings.bundle y su lista, ya que encontré que el editor plist de Xcode 4 tenía errores.

    Estos son los contenidos de mi Root.plist:

    <?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
    <plist version="1.0"> 
    <dict> 
    <key>StringsTable</key> 
    <string>Root</string> 
    <key>PreferenceSpecifiers</key> 
    <array> 
        <dict> 
         <key>Type</key> 
         <string>PSGroupSpecifier</string> 
         <key>Title</key> 
         <string>Authentication</string> 
        </dict> 
        <dict> 
         <key>Type</key> 
         <string>PSTextFieldSpecifier</string> 
         <key>Title</key> 
         <string>User ID</string> 
         <key>Key</key> 
         <string>user_id_key</string> 
         <key>DefaultValue</key> 
         <string>1234</string> 
         <key>IsSecure</key> 
         <false/> 
         <key>KeyboardType</key> 
         <string>Alphabet</string> 
         <key>AutocapitalizationType</key> 
         <string>None</string> 
         <key>AutocorrectionType</key> 
         <string>No</string> 
        </dict> 
    </array> 
    </dict> 
    </plist> 
    

    puedo acceder a los ajustes del menú de ajustes de iOS sin ningún problema y también cambiar el valor de la entrada única que tengo hasta ahora. El valor se almacena entre las sesiones en el simulador de iOS, así como en mi dispositivo físico iOS (un iPhone 4).

    Aparentemente, no puedo acceder a este valor desde mi código. Te voy a enseñar cómo me trató de ponerlo en práctica (en el ViewController.m de mi aplicación):

    - (void)viewDidLoad 
    { 
        [super viewDidLoad]; 
    
        myDefaults = [NSUserDefaults standardUserDefaults]; 
    
        // DEBUG 
        userID = [myDefaults stringForKey:@"user_id_key"]; 
        // userID = [NSString stringWithString:@"1234"]; 
    
        // DEBUG 
        jsonBackendURL = @"http://example.com/jsonBackend.php"; 
        passphrase  = @"secretPassphrase"; 
    
        theURLConnectionController = [[URLConnectionController alloc] initWithCallerObject:self]; 
        [theURLConnectionController getConnectionAndUpdate:NO]; 
    } 
    

    Curiosamente cuando trato de ejecutar la aplicación en Xcode 3 Yo ni recibe mensajes de error (como un SIGABRT o tal) ni ningún resultado de depurador. La pantalla del simulador de iPhone se queda en negro por un momento mientras intenta iniciar la aplicación y luego me llevan de vuelta a la pantalla de inicio.

    Xcode 4 muestra un comportamiento bastante extraño. Se las arregla para mostrar la interfaz de usuario de mi aplicación por un segundo o dos y luego me lleva de vuelta a la pantalla de inicio del simulador de iPhone. También indica un SIGABRT alguna manera más abajo en mi código donde intento de obtener un valor de una respuesta JSON:

    NSString *arrivalToday = [NSString stringWithString:[jsonResponse objectForKey:@"from"]]; 
    

    Como se genera la cadena JSON por un script PHP usando parámetros se pasan en mi aplicación - uno de estos el ID de usuario de Settings.bundle - no es de extrañar que esto no funcione. Sin embargo, no debería bloquearse ya que detecto este error antes en mi código, pero probablemente no esté conectado a mi problema de configuración. Sin embargo, un verdadero dolor en el cuello es el hecho de que Xcode (tipo de) falla junto con mi aplicación en el simulador de iPhone. En primer lugar, Xcode sigue funcionando normalmente, excepto por el hecho de que no puedo abortar el programa que aún parece ejecutarse. Puedo hacer clic en el botón de detener en Xcode pero sin ningún efecto. Cuando trato de salir de Xcode, me pregunta si debería terminar el programa en ejecución y cuando hago clic en Sí, se bloquea de verdad y tengo que forzarlo a salir.

    Afortunadamente, sin embargo, Xcode 4 me da una pila de llamadas de mi aplicación:

    2011-07-21 11:41:04.539 OneClickCheckIn[2098:b303] http://example.com/json.php?user=(null)&pass=secretPassphrase&getStartToday 
    2011-07-21 11:41:04.888 OneClickCheckIn[2098:b303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSPlaceholderString initWithString:]: nil argument' 
    *** Call stack at first throw: 
    (
    0 CoreFoundation      0x00de25a9 __exceptionPreprocess + 185 
    1 libobjc.A.dylib      0x00f36313 objc_exception_throw + 44 
    2 CoreFoundation      0x00d9aef8 +[NSException raise:format:arguments:] + 136 
    3 CoreFoundation      0x00d9ae6a +[NSException raise:format:] + 58 
    4 Foundation       0x007ca14c -[NSPlaceholderString initWithString:] + 105 
    5 Foundation       0x007d3266 +[NSString stringWithString:] + 72 
    6 OneClickCheckIn      0x00002b5c -[OneClickCheckInViewController updateInterfaceWithJsonResponse:] + 172 
    7 OneClickCheckIn      0x0000e82c -[URLConnectionControllerDelegate connectionDidFinishLoading:] + 364 
    8 Foundation       0x007de112 -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] + 108 
    9 Foundation       0x007de06b _NSURLConnectionDidFinishLoading + 133 
    10 CFNetwork       0x030fa48e _ZN19URLConnectionClient23_clientDidFinishLoadingEPNS_26ClientConnectionEventQueueE + 220 
    11 CFNetwork       0x031c56e1 _ZN19URLConnectionClient26ClientConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XClientEvent18XClientEventParamsEl + 293 
    12 CFNetwork       0x031c59cf _ZN19URLConnectionClient26ClientConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XClientEvent18XClientEventParamsEl + 1043 
    13 CFNetwork       0x030f0c80 _ZN19URLConnectionClient13processEventsEv + 100 
    14 CFNetwork       0x030f0acf _ZN17MultiplexerSource7performEv + 251 
    15 CoreFoundation      0x00dc38ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 
    16 CoreFoundation      0x00d2188b __CFRunLoopDoSources0 + 571 
    17 CoreFoundation      0x00d20d86 __CFRunLoopRun + 470 
    18 CoreFoundation      0x00d20840 CFRunLoopRunSpecific + 208 
    19 CoreFoundation      0x00d20761 CFRunLoopRunInMode + 97 
    20 GraphicsServices     0x0101a1c4 GSEventRunModal + 217 
    21 GraphicsServices     0x0101a289 GSEventRun + 115 
    22 UIKit        0x00042c93 UIApplicationMain + 1160 
    23 OneClickCheckIn      0x00002609 main + 121 
    24 OneClickCheckIn      0x00002585 start + 53 
    25 ???         0x00000001 0x0 + 1 
    ) 
    terminate called throwing an exception(lldb) 
    

    Esa es toda la información relevante que viene a la mente en este momento. He realizado una investigación exhaustiva en Google y también he leído algunos hilos en este sitio, pero no pude encontrar una solución.

    +0

    que he sido capaz de averiguar el problema con los Xcode 4 accidentes. Había configurado Xcode 4 para usar el nuevo depurador LLDP que aparentemente causó el bloqueo. Lo cambié de nuevo a GDB que resolvió el problema. – TigreFurry

    +0

    También he usado [sincronizar mis valores predeterminados] según lo sugerido por algunos que no cambiaron nada. – TigreFurry

    Respuesta

    0

    Como la cadena JSON es generada por un script PHP utilizando los parámetros GET pasados ​​por mi aplicación, una de estas es la ID de usuario de Settings.bundle, no es de extrañar que esto no funcione. Sin embargo, no debería bloquearse ya que detecto este error antes en mi código, pero probablemente no esté conectado a mi problema de configuración.Sin embargo, un verdadero dolor en el cuello es el hecho de que Xcode (tipo de) falla junto con mi aplicación en el simulador de iPhone. En primer lugar, Xcode sigue funcionando normalmente, excepto por el hecho de que no puedo abortar el programa que aún parece ejecutarse. Puedo hacer clic en el botón de detener en Xcode pero sin ningún efecto. Cuando trato de salir de Xcode, me pregunta si debería terminar el programa en ejecución y cuando hago clic en Sí, se bloquea de verdad y tengo que forzarlo a salir.

    Como se indicó anteriormente, esto se solucionó al cambiar el depurador a GDB. Además, resultó que el compilador al parecer, no le gustaba que he tratado de asignar un valor nulo a una NSString el que arrojó la excepción:

    NSString *arrivalToday = [NSString stringWithString:[jsonResponse objectForKey:@"from"]]; 
    

    i fijo esto comprobando si ([jsonResponse objectForKey: @ "de "] == nil) y ahora mi aplicación al menos ya no se cuelga. El problema NSUserDefaults persiste sin embargo.

    también he sido consultado por el siguiente tutorial:

    Adding a settings bundle to an iPhone App

    puedo configurar los valores por defecto en mis didFinishLaunchingWithOptions de aplicación tal como se describe en el artículo, pero en vano. Todavía no puedo acceder al valor de configuración de mi código.

    Agradecería una pista que me guíe en la dirección correcta ya que no tengo ni idea de qué podría explicar este extraño comportamiento.

    Gracias!

    7

    Finalmente he podido resolverlo gracias en gran parte a la guía mencionada anteriormente: Adding a settings bundle to an iPhone App.

    Allí se dice:

    [...] es importante entender que hasta que el usuario realmente cambia el valor del ajuste se establece nada en realidad. Si comprueba la configuración en su aplicación, en realidad devolverá cero a menos que establezca un valor predeterminado. Para ello, agregue el método siguiente a la applicationDidFinishLaunching (o didFinishLaunchingWithOptions):

    // Set the application defaults 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"YES" forKey:@"enableRotation"]; 
    [defaults registerDefaults:appDefaults]; 
    [defaults synchronize]; 
    

    yo no era consciente de ello. Además, me parece que los valores en NSDictionary tienen que inicializarse de alguna forma o que los cambios posteriores por parte del usuario tampoco tendrán efecto (intenté una y otra vez cambiar los valores en el simulador de iPhone mientras miraba para una solución y no funcionó). Aunque esto solo podría afectar al iPhone Simulator, aún no he tenido la oportunidad de probarlo en mi dispositivo físico. Mi código de inicialización ahora se ve así (en el AppDelegate):

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    { 
        // Override point for customization after application launch. 
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
        NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys: 
              @"1234", @"user_id_key", 
              @"http://example.com/json.php", @"json_url_key", 
              @"secretPassphrase", @"passphrase_key", 
              nil]; 
    
        [defaults registerDefaults:appDefaults]; 
        [defaults synchronize]; 
    
        self.window.rootViewController = self.viewController; 
        [self.window makeKeyAndVisible]; 
        return YES; 
    } 
    

    Con ese código que pueda acceder fácilmente a los valores NSUserDefaults más adelante en mi código:

    - (void) reloadPreferences { 
        myDefaults = [NSUserDefaults standardUserDefaults]; 
    
        userID   = [myDefaults objectForKey:@"user_id_key"]; 
        jsonBackendURL = [myDefaults objectForKey:@"json_url_key"]; 
        passphrase  = [myDefaults objectForKey:@"passphrase_key"]; 
    } 
    

    que también pasó algún tiempo cazando a una error relacionado con el orden de los pares clave-valor del NSDictionary hasta que caí en la cuenta de que el valor viene primero seguido de la clave en la definición. Procedente de un fondo de Perl, esto es un tanto extraño para mí, así que podría ser algo de lo que hay que tener cuidado si obtiene valores nulos de su objeto NSUserDefaults.

    Esto me costó unos tres días arreglarlo, así que espero que la solución pueda ser útil para algunos.:-)

    1

    El siguiente enlace me ayudó a comprender el comportamiento que está mencionando y espero que también lo ayude. En resumen, los valores predeterminados del conjunto de configuraciones no se copian en nsuserdefaults y deben registrarse manualmente. Los NSUserDefaults sólo se reflejarán los últimos valores que el usuario modifique la configuración de la aplicación, pero, no los valores por defecto

    http://ijure.org/wp/archives/179

    Cuestiones relacionadas