2011-07-21 60 views
8

我一直被动地使用本网站一段时间,并阅读了常见问题解答,所以我希望我能够将这些保持在最低限度。无法从Settings.bundle读取值

我对Objective-C中的Settings.bundle文件有疑问。我一直在使用以下指南来实现其中的一个:

  • How to create an iPhone preferences file
  • iOS Application Programming Guide - Implementing Application Preferences
  • 我同时使用的Xcode 4.1和最新的Xcode 3。我用3版创建Settings.bundle和它的plist,因为我发现Xcode 4的plist编辑器有些bug。

    这些都是我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> 
    

    我可以在iOS的设置菜单访问的设置没有问题,改变的是我迄今为止的单项的值。该值会在iOS模拟器以及我的物理iOS设备(iPhone 4)上的会话之间存储。

    但我似乎无法从我的代码中访问此值。让我告诉你我是如何设法实现它(在我的应用程序的ViewController.m):

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

    奇怪的是,当我尝试运行在Xcode 3的应用程序,我没有得到任何错误信息(如SIGABRT或者这样)或任何调试器输出。 iPhone模拟器的屏幕暂时变黑,因为它正在尝试启动应用程序,然后我被带回主屏幕。

    Xcode 4显示了一些相当奇怪的行为。它设法显示我的应用程序的用户界面一两秒钟,然后将我带回iPhone模拟器的主屏幕。这也预示着SIGABRT某种方式在我的代码,我尝试从一个JSON响应得到的值越往下:

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

    如通过使用我的应用程序传递GET参数的PHP脚本生成的JSON字符串 - 其中一个来自Settings.bundle的用户ID--毫无疑问,这不应该起作用。它不应该崩溃,因为我在我的代码中早些时候发现了这个错误,但这可能不会连接到我的设置问题。脖子上真正的痛苦是Xcode(种类)与iPhone模拟器中的应用程序一起崩溃。首先,Xcode保持正常工作,除了我不能中止仍然运行的程序。我可以点击Xcode中的停止按钮,但不起作用。当我尝试退出Xcode时,它询问我是否应该终止正在运行的程序,并且当我点击yes时,它会崩溃,我必须强制退出它。

    幸运的,虽然时,Xcode 4给我我的应用程序的调用堆栈:

    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) 
    

    这一切的来到我的脑海里,现在的相关信息。我已经对Google进行了广泛的研究,并且还阅读了本网站上的一些主题,但我找不到解决方案。

    +0

    我已经能够用Xcode的4崩溃弄清楚这个问题。我将Xcode 4配置为使用显然导致崩溃的新LLDP调试器。我将其改回到GDB解决了问题。 – TigreFurry

    +0

    我也使用 [myDefaults同步] 建议由一些没有改变任何东西。 – TigreFurry

    回答

    0

    由于JSON字符串是由PHP脚本使用由我的应用程序传入的GET参数生成的 - 这些来自Settings.bundle的用户ID之一 - 这是不奇怪的,这不应该工作。它不应该崩溃,因为我在我的代码中早些时候发现了这个错误,但这可能不会连接到我的设置问题。脖子上真正的痛苦是Xcode(种类)与iPhone模拟器中的应用程序一起崩溃。首先,Xcode保持正常工作,除了我不能中止仍然运行的程序。我可以点击Xcode中的停止按钮,但不起作用。当我尝试退出Xcode时,它询问我是否应该终止正在运行的程序,并且当我点击yes时,它会崩溃,我必须强制退出它。

    如上所述,通过将调试器更改为GDB可以解决这个问题。而且,事实证明,编译器显然不喜欢,我试图将一个零值赋给一个NSString引发异常:@“来源:

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

    我的,如果([jsonResponse objectForKey检查固定这“] ==无),现在我的应用程序至少不会崩溃了。但NSUserDefaults问题仍然存在。

    我也咨询了以下教程:

    Adding a settings bundle to an iPhone App

    我把我的应用程序didFinishLaunchingWithOptions中默认的文章中,但无济于事描述。我仍然无法从我的代码中访问设置值。

    我很感激有人提示引导我走向正确的方向,因为我完全无能为力,无法解释这种奇怪的行为。

    谢谢!

    7

    我终于能够解决它,主要归功于上述指南:Adding a settings bundle to an iPhone App

    有这样说的:

    [...]是要明白,直到用户实际上改变了什么设定的值实际设置是非常重要的。如果您检查应用程序中的设置,它将实际返回零,除非您设置了默认值。要做到这一点添加以下到的applicationDidFinishLaunching(或didFinishLaunchingWithOptions)方法:

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

    我没有意识到这一点。此外,在我看来,NSDictionary中的值必须以某种形式进行初始化,或者稍后用户的更改也不会生效(我一直试图在iPhone模拟器中一次又一次地更改值为解决方案,它不工作)。这可能只会影响iPhone模拟器,但我还没有机会在我的物理设备上进行测试。我的初始化代码现在看起来像这样(在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; 
    } 
    

    与该代码我可以方便地访问NSUserDefaults的值后来在我的代码:

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

    我也花了一些时间追捕一个关于NSDictionary的键值对的顺序的错误,直到它在我看到值先到后跟定义键。从Perl背景来看,这对我来说有些陌生,所以如果你从你的NSUserDefaults对象中获得nil值,可能需要注意一些事情。

    这花了我三天左右的时间来解决,所以我希望这个解决方案可能会派上用场。:-)

    1

    以下链接对我了解您提及的行为很有帮助,我希望能帮助您。简而言之,设置包的默认值不会复制到nsuserdefaults并需要手动注册。该会NSUserDefaults的仅反映用户修改的设置应用程序的最新值,但是,没有默认值

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