我一直在开发一个拼图游戏应用程序。我原本打算使用核心数据来保存拼图的进度,但我切换到使用属性列表文件,我认为效果更好。但现在我遇到了一个问题。
启动应用程序,它可以从头开始创建拼图,也可以根据 plist 文件中的信息创建拼图。当它从头开始创建它们时,我可以设置一个活动指示器,它在处理过程中非常准确地制作动画。
但是,当从属性列表数据重建时,在我的所有处理完成之后,仍然有某种活动会延迟初始显示。使用工具和 NSLog 语句,我在寻找延迟的根源方面没有取得任何进展。
然而,就在刚才,我决定在 NSLog 语句表明我的东西已经完成之后,但在显示完成之前暂停应用程序。我穿过一个随机的线程,当我这样做时,我的观点突然出现了。
该线程(线程 24)在其下有一个称为 CFPreferences Background Sync Queue 的描述。我的视图出现时屏幕上的块是这样的:
libdispatch.dylib`_dispatch_call_block_and_release:
0x3c6fa114: push {r4, r7, lr}
0x3c6fa116: mov r4, r0
0x3c6fa118: add r7, sp, #4
0x3c6fa11a: ldr r1, [r4, #12]
0x3c6fa11c: blx r1
0x3c6fa11e: mov r0, r4
0x3c6fa120: pop.w {r4, r7, lr}
0x3c6fa124: b.w 0x3c7127dc ; _Block_release$shim
请注意,我在这里没有使用 NSUserDefaults,而是使用单独的属性列表。我就这样使用它们:
NSError *error;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist",self.leftImage.imageName]];
NSData *plistData = [NSData dataWithContentsOfFile:plistPath];
BOOL returnValue = YES;
if(plistData) {
NSPropertyListFormat format;
NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:&format error:&error];
if (plist) { .. etc.
在这里,我使用 plist 中的数据来创建我需要使用 dispatch_async 的对象。我没有更新从磁盘检索到的任何列表,所以我不确定需要同步哪些内容,但似乎导致延迟的过程与属性列表同步有关(只是我基于名称的预感我看到了)。
任何有关如何解决此问题的提示将不胜感激。
PS 我添加-(void)didMoveToWindow
到我所有的 UIView 子类中,当触发时,我检查了 self.window。据说这可以用来检查视图是否出现在窗口中。在所有情况下, self.window 都有一个值,并且该didMoveToWindow
方法在我发布的延迟之前被调用。如果自动布局正在做很多事情,我尝试将其关闭,但这并没有什么不同。我还确保在完成数据后立即将每个字典和 plist 变量设置为 nil,这也没有什么不同。正如你所看到的,我现在正抓着稻草。
PPS 如果有帮助,这里列出了延迟期间调用的方法。每个方法前面的数字是在延迟期间被调用的次数。我通过在每个异步块的末尾调用一个名为 GENERICMARKFORASYNC_ _ __ _ENDOFMARK的空方法来确定延迟期的开始。我对主代码有类似的标记,但异步代码不出所料地最后完成。我通过在视图最终出现后移动视图并寻找在日志中识别的平移手势来确定延迟的结束。