我对小翅膀的错误修复有一个奇怪的问题。在我的游戏中,我使用类似的东西:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setFloat:musicVolume forKey:@"musicVolume"];
用于保存一些首选项和高分表。在游戏结束时,当游戏结束屏幕出现时,游戏会将高分保存到标准用户默认值中。它运行良好,直到游戏显示如下的UIAlertView:
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setTitle:@"Get ready!"];
[alert setDelegate:self];
[alert addButtonWithTitle:@"Ok"];
[alert show];
[alert release];
每次游戏将某些内容保存到标准用户默认值时,警报视图消失后,游戏会滞后一段时间(在某些设备上会滞后几秒钟)。这也发生在游戏使用 UITextField 输入玩家姓名之后。在使用两个UIKit元素之一之前,游戏中没有任何延迟,但是在使用它们之后,游戏会滞后,直到我重新启动应用程序。我分析了性能工具的问题,"I/O 活动"工具显示有数百个"打开 - 读取 - 关闭"访问
/System/Library/Frameworks/UIKit.framework/InputModeProperties.plist
这会导致滞后。
我完全不知道该怎么办。有什么想法吗?
编辑:
苹果开发者论坛 http://devforums.apple.com/message/424374#424374 中有一个帖子,有人有同样的问题,似乎它只出现在iOS 4.3中。我已经测试过它,滞后只发生在我的 4.3 设备上(不是在 3.1 iPod touch 和 4.2 iPad 上)。
编辑
一个不错的错误解决方法:
简短版本:只需延迟错误触发调用,直到用户不烦恼。
长版本:
由于我认为问题来自[NSUserDefaults standardUserDefaults]
调用,因此在请求键盘布局(如UIAlert
)的某些操作之后,它会触发肮脏的 plist-load 循环......
我建议在应用程序加载时只调用[NSUserDefaults standardUserDefaults]
一次(在任何导致错误的调用之前),并在所有应用程序生命周期中将返回的引用保留在单例类中。我不认为内存占用会很大...(我在几个应用程序中执行此操作,没有任何问题)。在更糟糕的情况下,plist 加载*100 只会在应用程序加载时执行一次,而不是在游戏期间完成。
如果问题来自[userDefaults setXxxx:...]
调用,同样的解决方法,您可以保留要保存在内存中的值,稍后在 userDefaults
中设置它们,就像在同步它们之前一样......但如果出现任何问题,例如崩溃,则冒着丢失信息的风险。我个人更喜欢在每次set
后sync
以确保数据完整性......
结束编辑
简短的回答:iOS4.3错误,找到解决方法的机会很少...错误报告并等待下一次iOS更新...WWDC 在 2 周内...1~2个月。
长的一个:
在看了UIKit组合之后,以下是我的猜测:
-
InputModeProperties.plist
包含按区域设置列出的所有键盘布局的列表。 -
UIKit
将其用于多种用途,例如在显示键盘时,以确定可用的键盘布局。(区域设置... -
有一件事很有趣,我们可以在
NSUserDefaults
中找到它的一些信息:NSLog(@"%@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]); ==> { AppleKeyboards = ( // I have two keyboard in preferences "fr_FR@hw=French;sw=AZERTY", // french first "en_US@hw=US;sw=QWERTY" // english second ); ...
- 但这些信息不会存储在应用偏好设置中,这与你的分数不同。(
NSGlobalDomain
,或者更可能是为每种用户的首选语言提供单独的域) - 所以我不会感到惊讶 UIKit + NSUserDefaults 中存在冲突(错误)导致脏列表加载循环。
- 你说100个左右的电话?这有点像 plist 中的区域设置/布局数量!
当NSUserDefaults
中没有可用的键盘时...(就像同步后一样,让我们想象一个错误这样做)... UIKit
可以尝试所有可用的键盘来确定用户 1,肮脏地解析这个 4.4K 列表一百次......就像展示UIAlertView
一样...NSUSerDefault
同步/更改后。
谁知道呢?拥有源代码的苹果人:)
我不会感到惊讶,去首选项设置默认美国以外的键盘,然后恢复到美国将解决问题。在您的情况下没用,但会确认问题。看到另一个 4.3 错误...
正如其他人所说,不使用NSUserDefaults而是在/Documents中使用简单的自定义plist可能是一个(不)体面的解决方法。
《小翅膀》做得很好! :)
好的,环顾四周,似乎InputModeProperties.plist只是一个硬件和软件键盘的列表。
查看您发布的论坛主题,此问题似乎本质上是在加载UITextField对象或UIAlertView(包括UITextInputTraits.h等)后,每当尝试保存用户默认值时,都会有一个莫名其妙的键盘定义循环文件。这只发生在iOS 4.3中。
对我来说,这似乎非常像 UIKit 中的一个错误,我的猜测是 UIKit 突然在没有真正目的的情况下节省了大量东西。如果是这种情况,尽管您可以避免这些元素(对于警报来说还不错,但文本字段会更棘手),或者您可以切换到核心数据,但您可能很难对此做任何事情。或者,您可以为所有选项创建一个可变字典,并在应用程序关闭时将其保存为用户默认值,并且您不太关心暂停。或者,只是完成更新。
祝你好运(顺便说一句,喜欢游戏)
建议同时使用 UIKit 和 OpenGL。我不认为这种观点是问题,而是将两者混合的概念。我强烈建议取消该警报,而是显示自定义覆盖,以便您可以完成两件事:
- 使"准备就绪"警报与游戏图形匹配。
- 完全避免此问题。
我在App Store上看到当前发布的版本在第二代iPod touch上恢复游戏时性能缓慢。
如果你想保持这些元素不变,这篇 Apple 开发者论坛帖子建议在单独的线程上运行同步。除此之外,我建议采取以下步骤:
正如其他人建议的那样,在某处保留对NSUserDefaults的引用。(我通常只是做这样的事情:
#define kSettings [NSUserDefaults standardUserDefaults]
。当然,您需要调用它一次才能实例化单例。在第二个线程上运行
synchronize
调用(根据 Apple 开发人员论坛帖子)。看看您是否可以在
willResignActive
以外的其他时间呼叫synchronize
。当您从该方法调用同步时,问题似乎更糟。
恭喜游戏。
只是在黑暗中查看 4.3 差异的镜头 -
也许是新的组合
- (BOOL)disablesAutomaticKeyboardDismissal
UIViewController 和 UIModalPresentationFormSheet(默认为 YES)导致代码中的某种循环。
假设您执行了一个方法来显示警报视图,您是否尝试过以下方法?
[self performSelector:@selector(displayAlert) withObject:nil afterDelay:0.5];
- (void)displayAlert {
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setTitle:@"Get ready!"];
[alert setDelegate:self];
[alert addButtonWithTitle:@"Ok"];
[alert show];
[alert release];
}
我问的原因是,在同步NSUserDefaults
后尝试直接执行方法时,我经常遇到奇怪的行为。否则,我们真的需要看到更多的代码才能确定发生了什么。
可能它将每个选项保存为单独的事务。我不确定。您可以尝试使用自己的单例数据存储类和NSMutableDictonairy作为数据存储。并将其同步到 NSUserDefaults on applicationDidEnterBackground:
和 applicationWillTerminate:
.或者,即使您没有将系统设置与NSUserDefaults一起使用,您也可以按如下方式保存此NSMutableDictonairy:
tempData = [NSMutableData data];
archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:tempData];
[archiver encodeObject:mutableDict forKey:@"data"];
[archiver finishEncoding];
result = [tempData writeToFile:archivePath atomically:YES];
[archiver release];
附言为小翅膀竖起大拇指。 ;)