Objective c 无法从Settings.bundle读取值
我已经被动地使用这个网站有一段时间了,并且已经阅读了FAQ,所以我希望我能够将这些保持在最低限度 我对Objective-C中的Settings.bundle文件有一个问题。我一直在使用以下指南来实现其中一个: 我使用的是Xcode 4.1和最新的Xcode 3。我使用版本3创建Settings.bundle及其plist,因为我发现Xcode 4的plist编辑器有点缺陷 以下是my Root.plist的内容:Objective c 无法从Settings.bundle读取值,objective-c,xcode4,settings.bundle,root.plist,Objective C,Xcode4,Settings.bundle,Root.plist,我已经被动地使用这个网站有一段时间了,并且已经阅读了FAQ,所以我希望我能够将这些保持在最低限度 我对Objective-C中的Settings.bundle文件有一个问题。我一直在使用以下指南来实现其中一个: 我使用的是Xcode 4.1和最新的Xcode 3。我使用版本3创建Settings.bundle及其plist,因为我发现Xcode 4的plist编辑器有点缺陷 以下是my Root.plist的内容: <?xml version="1.0" encoding="UTF
<?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>
奇怪的是,当我尝试在Xcode 3中运行应用程序时,我既没有收到任何错误消息(比如SIGABRT之类的),也没有收到任何调试器输出。iPhone模拟器的屏幕在尝试启动应用程序时变黑了一会儿,然后我被带回到主屏幕
Xcode 4显示了一些相当奇怪的行为。它设法在一两秒钟内显示我的应用程序的UI,然后将我带回iPhone模拟器的主屏幕。它还表示在我的代码中,我试图从JSON响应中获取一个值的某个地方有一个SIGABRT:
NSString *arrivalToday = [NSString stringWithString:[jsonResponse objectForKey:@"from"]];
由于JSON字符串是由PHP脚本使用我的应用程序传入的GET参数生成的,其中一个参数是Settings.bundle中的用户ID,所以这不起作用也就不足为奇了。不过,它不应该崩溃,因为我在代码的前面捕捉到了这个错误,但这可能与我的设置问题无关。但真正让人头疼的是,在iPhone模拟器中,Xcode(有点)与我的应用程序一起崩溃。首先,Xcode保持正常工作,除了无法中止仍在运行的程序。我可以在Xcode中单击停止按钮,但没有效果。当我试图退出Xcode时,它会询问我是否应该终止正在运行的程序,当我单击“是”时,它会真正崩溃,我必须强制退出它
幸运的是,Xcode 4为我的应用程序提供了一个调用堆栈:
- (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];
}
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)
这就是我现在想到的所有相关信息。我对谷歌做了广泛的研究,也在这个网站上读了一些帖子,但我找不到解决办法
由于JSON字符串是由PHP脚本使用我的应用程序传入的GET参数生成的,其中一个参数是Settings.bundle中的用户ID,所以这不起作用也就不足为奇了。不过,它不应该崩溃,因为我在代码的前面捕捉到了这个错误,但这可能与我的设置问题无关。但真正让人头疼的是,在iPhone模拟器中,Xcode(有点)与我的应用程序一起崩溃。首先,Xcode保持正常工作,除了无法中止仍在运行的程序。我可以在Xcode中单击停止按钮,但没有效果。当我试图退出Xcode时,它会询问我是否应该终止正在运行的程序,当我单击“是”时,它会真正崩溃,我必须强制退出它
如上所述,这是通过将调试器更改为GDB来修复的。此外,编译器显然不喜欢我尝试为引发异常的NSString分配一个nil值:
NSString *arrivalToday = [NSString stringWithString:[jsonResponse objectForKey:@"from"]];
我通过检查([jsonResponse objectForKey:@“from”]==nil)修复了这个问题,现在我的应用程序至少不再崩溃了。不过,NSUserDefaults问题仍然存在
我还参考了以下教程:
我在应用程序didFinishLaunchingWithOptions中设置了默认值,如本文所述,但没有效果。我仍然无法从代码中访问设置值
如果能给我一个提示,指引我正确的方向,我将不胜感激,因为我完全不知道是什么可以解释这种奇怪的行为
谢谢 多亏了上面提到的指南,我终于能够解决这个问题了: 上面写着: […]重要的是要理解,在用户实际更改设置值之前,不会实际设置任何内容。如果在应用程序中检查设置,除非设置默认值,否则它实际上将返回nil。为此,请将以下内容添加到ApplicationIDFinishLaunching(或didFinishLaunchingWithOptions)方法中: 我不知道。此外,在我看来,NSDictionary中的值必须以某种形式初始化,否则用户稍后所做的更改也不会生效(我在寻找解决方案时曾多次尝试在iPhone模拟器中更改这些值,但都没有成功)。这可能只会影响iPhone模拟器,但我还没有机会在我的物理设备上测试它。我的初始化代码现在如下所示(在AppDelegate中): 使用该代码,我可以轻松访问代码后面的NSUserDefaults值:
- (void) reloadPreferences {
myDefaults = [NSUserDefaults standardUserDefaults];
userID = [myDefaults objectForKey:@"user_id_key"];
jsonBackendURL = [myDefaults objectForKey:@"json_url_key"];
passphrase = [myDefaults objectForKey:@"passphrase_key"];
}
我还花了一些时间寻找一个关于NSDictionary的键值对顺序的bug,直到我意识到在定义中,值在键值之后。来自Perl背景,这对我来说有点陌生,所以如果从NSUserDefaults对象获得零值,可能需要注意这一点
这花费了我大约三天的时间来修复,所以我希望这个解决方案可能会对一些人有用。:-) 下面的链接有助于我理解您提到的行为,我希望也能对您有所帮助。简而言之,设置包的默认值不会复制到nsuserdefaults,需要手动注册。nsuserdefaults将仅反映用户在设置应用程序中修改的最新值,而不是默认值
我已经能够解决Xcode 4崩溃的问题。我将Xcode 4配置为使用新的LLDP调试器,这显然是导致崩溃的原因。我把它改回了GDB,解决了这个问题。我还按照一些人的建议使用了[myDefaults synchronize],但没有改变任何东西。
- (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;
}
- (void) reloadPreferences {
myDefaults = [NSUserDefaults standardUserDefaults];
userID = [myDefaults objectForKey:@"user_id_key"];
jsonBackendURL = [myDefaults objectForKey:@"json_url_key"];
passphrase = [myDefaults objectForKey:@"passphrase_key"];
}