这里发生了啥?核心数据/iCloud
Posted
技术标签:
【中文标题】这里发生了啥?核心数据/iCloud【英文标题】:Does anyone know whats going on here ? Core Data / iCloud有谁知道这里发生了什么?核心数据/iCloud 【发布时间】:2013-10-15 23:47:30 【问题描述】:所以这里发生的事情是该应用刚刚收到NSPersistentStoreDidImportUbiquitousContentChangesNotification
,而我刚刚调用了
- (void)storesDidUpdate:(NSNotification*)note
FLOG(@"storesDidUpdate ");
[_managedObjectContext mergeChangesFromContextDidSaveNotification:note];
// Refresh user Interface
[[NSNotificationCenter defaultCenter] postNotificationName:@"iProjectCoreDataUpdated"
object:self];
[self updateDetails];
现在,应用程序正在尝试通过简单地执行以下操作来使用新的文本副本更新 UITextView:
self.detailText.attributedText = [self.detailItem valueForKey:@"scope"];
其中 detailItem 是在从 iCloud 接收更新之前检索到的 NSManagedObject。
不知道为什么 textContainer 会抱怨或抱怨什么,也不知道为什么会发生导入日志,因为我已经收到通知说它已经完成了!
奇怪的是,如果我调用 reloadData,其他 UITableViews 会正确更新。
关于我是否在这里做错了什么有什么想法吗?请注意,如果我不尝试更新 textView 它工作正常,如果我关闭视图并返回它,那么我会得到正确的数据。
此外,当我重新启动应用程序时,所有数据都在那里,没有损坏或任何东西,事实上,尽管 iCloud 两边都出现了问题,但该应用程序在大多数方面在核心数据存储方面看起来都非常强大!
哦,reloadFetchedResults 有点误导,因为我似乎不需要这样做,所以方法名称是过去的遗留物,我所做的只是在此调用中刷新 UI 中的值。
2013-10-09 07:25:53.783 MyApp[4509:510b] OpeningViewController.reloadFetchedResults:调用 2013-10-09 07:25:53.786 MyApp [4509:510b] InfoDetailViewController.reloadFetchedResults:在 InfoDetailViewController 中调用 2013-10-09 07:25:53.788 MyApp[4509:510b] * void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView *, NSTextContainer *, NSUInteger)() 中的断言失败, /SourceCache/UIFoundation/UIFoundation-258/UIFoundation /TextSystem/NSLayoutManager_Private.m:1510 2013-10-09 07:25:53.793 MyApp [4509:510b] -_PFUbiquityRecordImportOperation main:CoreData:Ubiquity:导入事务日志时出错: transactionLogLocation::/var/mobile/Library/Mobile Documents/HHHHHHNNNN~com~mycompany~MyApp/CoreData/New Document/duncangroenewald~simAABC628E-9D5E-58F7-9B8D-0BC724C6D0C8/New Document/W8MckEJ0x2d~HZZIeUH2be6hs41-CAFONzKIrCuLcuB4= 47F7-B828-DD062B96415D.1.cdt 交易编号:5 ,例外:只在主线程上运行! 用户信息:(空) 2013-10-09 07:25:53.803 MyApp[4509:510b] -_PFUbiquityRecordsImporter 操作:failedWithError:: CoreData:Ubiquity:导入操作遇到错误:Error Domain=NSCocoaErrorDomain Code=134060“操作无法完成。( Cocoa 错误 134060.)" UserInfo=0x16d882c0 exception=仅在主线程上运行! 用户信息: exception = "只在主线程上运行!"; 。尝试在 URL 处导入日志文件时: transactionLogLocation::/var/mobile/Library/Mobile Documents/HHHHHHNNNN~com~mycompany~MyApp/CoreData/New Document/duncangroenewald~simAABC628E-9D5E-58F7-9B8D-0BC724C6D0C8/New Document/W8MckEJ0x2d~HZZIeUH2be6hs41-CAFONzKIrCuLcuB4= 47F7-B828-DD062B96415D.1.cdt 交易编号:5 2013-10-09 07:25:53.809 MyApp[4509:510b] * 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“仅在主线程上运行!” *** 首先抛出调用堆栈: (0x2ff23f53 0x3a6996af 0x2ff23e2d 0x308cb1df 0x3796643d 0x37966185 0x3798f7bb 0x379926f7 0x37992759 0x379b378b 0x379b331f 0x379b2f0d 0x3273b05d 0x129717 0x2fee6121 0x2fe5a317 0x3083edcd 0x308436ab 0x118263 0x2fee6121 0x2fe5a317 0x2fd8c69f 0x2fd8cc93 0x2fd813dd 0x3085197b 0x308f5b35 0x3ab83297 0x3ab8309b 0x3ab83d15 0x3ab83f8d 0x3acbedbf 0x3acbec84) libc++abi.dylib:以 NSException 类型的未捕获异常终止
编辑: 我在这里发布了一些适用于 ios 和 OSX 的示例 Core Data/iCloud 应用程序 - 它们包括用于加载/删除数据以及 iCloud 同步的后台线程。希望解决这里描述的问题。 http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/
【问题讨论】:
奇怪的是,在其他视图上完全相同的代码似乎可以毫无问题地更新 UI。 很难确定,但错误消息反复显示Only run on the main thread!
这一事实可能是一个需要立即认真考虑的大、大、巨大、重要的线索。
汤姆见下面的附加信息...
【参考方案1】:
好的,这似乎可以解决它 - 我想我从未意识到接收通知会在另一个线程上运行。这是正常行为吗,您收到的所有核心数据通知都是在后台线程上调用的吗?如果是这样,您是否总是必须确保您所做的任何事情都在正确的线程上运行?
- (void)storesDidUpdate:(NSNotification*)note
FLOG(@"storesDidUpdate ");
[_managedObjectContext mergeChangesFromContextDidSaveNotification:note];
[[NSOperationQueue mainQueue] addOperationWithBlock:^
//Your code goes in here
LOG(@" Main Thread Code");
// Refresh user Interface
[[NSNotificationCenter defaultCenter] postNotificationName:@"CoreDataUpdatedNotification"
object:self];
];
编辑:
我终于开始记录我是如何让 Core Data 和 iCloud 相当可靠地工作的,包括处理进出 iCloud 以响应用户更改他们的使用 iCloud 首选项设置。当我试图弄清楚如何让它工作时,我无法用工作代码找到一个很好的解释,所以我希望这对其他人有用。包括一个应用程序工作的视频,因此您可以查看它的行为方式,以帮助您确定它是否是您想要实现的目标。
http://ossh.com.au/design-and-technology/software-development/
【讨论】:
哦,我也应该在主线程上调用 mergeChangesFromContext... 吗? 在发布它们的线程上收到通知。对于大多数 Core Data 通知,这意味着您正在使用的任何线程。使用 iCloud 则不一定如此。 糟糕!谢谢汤姆,现在一切看起来都很稳定。我仍在尝试破坏数据库,但尽管其他人说 Core Data 和 iCloud 不可靠,但我还是没能做到。它是可靠的还是我不够努力。 在 iOS 7 中比以前更好了,但我还没有足够的测试来说明它是否可靠。 是的,NSNotifications 可以来自不同的线程,也可能来自不属于你或你不知道的线程。【参考方案2】:我遇到了同样的问题。这正是@John Rogers 解释的问题。
我创建了UITextViews
,并在后台调用了一个URL 来获取一些数据,这些数据应该插入到我生成的UITextView
s 中。但问题是方法sendAsynchronousRequest
将在后台调用并在我的情况下导致崩溃。
我可以通过在接收我的数据时在主线程上执行特定的选择器来解决这个问题。所以也许你可以将你的方法调用插入另一个方法并以这种方式调用它:
[self performSelectorOnMainThread:@selector(received:)
withObject:data
waitUntilDone:YES];
这样你又回到了主线程。
【讨论】:
【参考方案3】:阅读所有答案+cmets(以及您的修复) - 我认为应该注意您必须仅从主线程更新任何 UI 控件。
我假设[self updateDetails];
调用self.detailText.attributedText = [self.detailItem valueForKey:@"scope"];
代码?...更新 UI 的实际代码是什么?
假设,那么您可以使用 -performSelectorOnMainThread 执行对 -updateDetails 的调用:或在 -updateDetails 中检查您是否在主线程 ([NSThread isMainThread]
) 上执行并在那里包装 UI 更新代码,以便调用者不会不在乎他们从哪个线程调用 -updateDetails。
【讨论】:
正如您在我的回答中看到的那样,我现在总是从主线程发布我的通知,因此任何 UI 更新代码总是在主线程上被调用。我不再使用我发布的初始代码。现在每个 UIViewController 都会监听我的通知,该通知发布在主线程上,然后调用一个方法 -(void)displayDetails,其中包含 UI 更新代码,例如上面的代码提取。 是的,您应该能够包装更新代码,使其始终在主线程上执行。但是,我不这样做,因为不仅 UI 更新必须在主线程上,对来自主 managedObjectContext 的对象的任何操作也必须在主线程上。【参考方案4】:是的,我明白了,但我没有在任何线程上做任何事情,所以必须做其他事情。我正在更新 UITextView,我猜它可能导致失败。我不清楚为什么这与 ubiquityImporter 有任何关系——也许能够解释下面这些内容的人可以为我指明正确的方向。我是不是在错误的线程上运行了一些东西?
First throw call stack:
(
0 CoreFoundation 0x027c55e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x019238b6 objc_exception_throw + 44
2 CoreFoundation 0x027c5448 +[NSException raise:format:arguments:] + 136
3 Foundation 0x01062960 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 101
4 UIFoundation 0x01b33131 -[NSLayoutManager(NSPrivate) _resizeTextViewForTextContainer:] + 419
5 UIFoundation 0x01b32e16 -[NSLayoutManager(NSPrivate) _recalculateUsageForTextContainerAtIndex:] + 2083
6 UIFoundation 0x01b67675 _enableTextViewResizing + 234
7 UIFoundation 0x01b6b275 -[NSLayoutManager textStorage:edited:range:changeInLength:invalidatedRange:] + 688
8 UIFoundation 0x01b6b2fa -[NSLayoutManager processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:] + 82
9 UIFoundation 0x01b93d35 -[NSTextStorage _notifyEdited:range:changeInLength:invalidatedRange:] + 153
10 UIFoundation 0x01b93870 -[NSTextStorage processEditing] + 462
11 UIFoundation 0x01b93419 -[NSTextStorage endEditing] + 80
12 UIFoundation 0x01b934a3 -[NSTextStorage coordinateEditing:] + 66
13 UIKit 0x007f4f48 -[UITextView setAttributedText:] + 254
14 MyApp 0x00027d7a -[WBSDetailViewController displayItem] + 3146
15 MyApp 0x00028c6c -[WBSDetailViewController refreshUI:] + 156
16 Foundation 0x01088e39 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
17 CoreFoundation 0x02821524 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
18 CoreFoundation 0x0277907b _CFXNotificationPost + 2859
19 Foundation 0x00fc2b91 -[NSNotificationCenter postNotificationName:object:userInfo:] + 98
20 Foundation 0x00fd206a -[NSNotificationCenter postNotificationName:object:] + 55
21 MyApp 0x00031095 -[BaseAppDelegate storesDidUpdate:] + 293
22 Foundation 0x01088e39 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
23 CoreFoundation 0x02821524 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
24 CoreFoundation 0x0277907b _CFXNotificationPost + 2859
25 Foundation 0x00fddd7b -[NSNotificationCenter postNotification:] + 121
26 CoreData 0x0173c5f4 -[_PFUbiquityRecordsImporter postImportNotificationForStoreName:andLocalPeerID:withUserInfo:] + 1892
27 CoreData 0x0173cbc2 -[_PFUbiquityRecordsImporter operationDidFinish:] + 706
28 CoreData 0x0172e8ce -[_PFUbiquityRecordImportOperation main] + 15102
29 Foundation 0x0108aa69 -[__NSOperationInternal _start:] + 671
30 Foundation 0x01007798 -[NSOperation start] + 83
31 Foundation 0x0108cd34 __NSOQSchedule_f + 62
32 libdispatch.dylib 0x05b794b0 _dispatch_client_callout + 14
33 libdispatch.dylib 0x05b67088 _dispatch_queue_drain + 450
34 libdispatch.dylib 0x05b66e85 _dispatch_queue_invoke + 126
35 libdispatch.dylib 0x05b67e25 _dispatch_root_queue_drain + 83
36 libdispatch.dylib 0x05b6813d _dispatch_worker_thread2 + 39
37 libsystem_pthread.dylib 0x05f05dab _pthread_wqthread + 336
38 libsystem_pthread.dylib 0x05f09cce start_wqthread + 30
)
libc++abi.dylib: terminating with uncaught exception of type NSException
【讨论】:
当您遇到崩溃时,请注意 Xcode 左侧窗格中试图调用该方法的线程。如果不是 com.apple.main-thread,您将不得不在主队列上使用 GCD 调用您的代码。以上是关于这里发生了啥?核心数据/iCloud的主要内容,如果未能解决你的问题,请参考以下文章