我正处于创建应用程序的早期阶段,我希望保存,同步和备份数据.该应用程序不会将任何文件仅存储在数据库中.它将是iOS 8及以上,因此我可以使用CloudKit.我做了一些研究,但仍不清楚Core Data,iCloud和CloudKit如何协同工作.
据了解,CloudKit只是一种从云端获取和检索数据的方法.CloudKit是一种与iCloud同步数据的不同方式吗?
我的问题是:
如果我确实使用CloudKit,我还需要创建本地核心数据库吗?
如果数据仅存储在云中,则当iOS设备未连接到互联网时,用户可以访问该数据.我读到CloudKit只有有限的缓存.
如果有人能够在离线和在线保存和同步核心数据数据库的过程中分解每种技术的作用.
我目前的理解是:
核心数据用于在本地存储数据
iCloud将数据和存储同步到云中
CloudKit能够在云中存储和管理数据吗?
我希望我提供了足够的信息来解决这个问题.
作为初学者,我正在努力与iCloud合作.有一些样本,但它们通常非常详细(在开发者论坛上有一个用于iCloud和CoreData的大量).在苹果的文档都OK,但我仍然无法看到大局.所以请耐心等待,其中一些问题非常重要,但可能很容易回答.
上下文:我有一个非常简单的iCloud应用程序运行(下面的完整示例代码).只有一个UITextView显示给用户,他/她的输入保存在名为text.txt的文件中.

txt文件被推送到云端并可供所有设备使用.效果很好,但是:
主要问题:不使用iCloud的用户怎么办?
当我启动我的应用程序(请参阅下面的代码)时,我会检查用户是否启用了iCloud.如果启用了iCloud,一切都很好.该应用程序继续前进,在云端查找text.txt.如果找到,它将加载它并将其显示给用户.如果在云中找不到text.txt,它将只创建一个新的text.txt并将其显示给用户.
如果用户未启用iCloud,则不会发生任何事情.如何让非iCloud用户仍然可以使用我的文本应用程序?或者我只是忽略它们?我是否需要为非iCloud用户编写单独的功能?即我只是从文档文件夹中加载text.txt的函数?
处理iCloud中的文件的方式与处理应用程序沙箱中的所有其他文件的方式相同.
但是,在我的情况下,没有"正常"的应用程序沙箱了.它在云端.或者我是否总是首先从磁盘加载我的text.txt然后检查iCloud是否有更新的东西?
相关问题:文件结构 - 沙箱与云
也许我的主要问题是对iCloud应该如何工作的基本误解.当我创建一个UIDocument的新实例时,我将不得不覆盖两个方法.首先- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError从云端获取文件,然后-(id)contentsForType:(NSString *)typeName error:(NSError **)outError将文件导入云端.
我是否必须合并单独的功能,这些功能还会将text.txt的本地副本保存到我的沙盒中?这适用于非iCloud用户吗?据我了解iCloud,它会自动保存text.txt的本地副本.因此,我不应该需要将任何内容保存到我的应用程序的"旧"沙箱中(即过去曾经是旧的,在iCloud之前的日子).现在,我的沙箱完全是空的,但我不知道这是否正确.我应该在那里保留另一份text.txt吗?这感觉就像是混乱了我的数据结构...因为云中有一个text.txt,一个位于我设备上的iCloud沙箱中(即使我离线也会工作),还有一个位于旧沙箱中的第三个我的应用......
我的代码:一个简单的iCloud示例代码
这基于我在开发人员论坛和WWDC会话视频中找到的示例.我将它剥离到最低限度.我不确定我的MVC结构是否有用.该模型在AppDelegate中并不理想.欢迎任何改善它的建议.
编辑:我试图提取主要问题并发布[在这里].4
概述:

从云中加载text.txt的最重要的一点:
// AppDelegate.h
// iCloudText
#import <UIKit/UIKit.h>
@class ViewController;
@class MyTextDocument;
@interface AppDelegate : UIResponder <UIApplicationDelegate> {
NSMetadataQuery *_query;
}
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *viewController;
@property (strong, nonatomic) MyTextDocument *document;
@end
// AppDelegate.m
// iCloudText
#import "AppDelegate.h"
#import "MyTextDocument.h"
#import …Run Code Online (Sandbox Code Playgroud) CoreDataCoreData使用级联删除规则,实体"A"与条目"B" 的集合具有一对多的关系.
在iCloud环境中,当设备1显示"B"条目之一的详细视图时,设备2删除"A"条目.
当NSPersistentStoreDidImportUbiquitousContentChangesNotification在设备1中接收到通知时,其App Delegate调用mergeChangesFromContextDidSaveNotification然后广播内部通知,该内部通知由视图控制器捕获,显示条目"B"的细节(代码使用performBlock它应该的位置).
但是,尽管当详细视图控制器接收到内部通知时,条目"A"确实无效,但条目"B"仍然作为有效CoreData对象存在.似乎Cascade规则尚未完成其运作.因此,设备1中的视图控制器不知道删除,这可能导致意外的结果.
mergeChangesFromContextDidSaveNotification 当基础数据已合并但Cascade规则尚未完成时,似乎过早地返回.
我在通知到达时尝试刷新条目"B",同时暂时将stalenessInterval托管对象上下文设置为零,因此不会使用缓存对象,但我仍然从商店获得有效条目"B".
此时检查null条目"A"不是一个选项,因为情况比我在此描述的情况稍微复杂一些,并且空条目"A"在某些情况下可能有效.
我尝试在合并更改之后和将内部通知发送到视图控制器之前引入延迟.我发现2秒延迟没有帮助,但延迟10秒有效.
但我不想依赖这种延迟.这是一个没有太多数据的测试环境,我不知道在生产环境中会发生什么.依靠实验性延迟似乎不是正确的做法.
有没有正确的事情?或者我开始做错了什么?
我正在测试我使用的应用程序iCloud.有时,当我启动应用程序时,我在控制台中收到以下警告:
GEOResourceManifestServerRemoteProxy: Lost connection to geod
Run Code Online (Sandbox Code Playgroud)
一旦我收到此警告,我似乎无法获得任何数据iCloud.我试过搜索这个问题,但发现的信息很少.
有关如何尝试检测此问题并尝试处理它的任何建议?
所以,它终于发生了.发生了任何独立iPhone开发人员的最糟糕情况.升级我的应用程序后,有几个用户报告完全数据丢失.iCloud核心数据同步无法正常工作.我的用户正在部分使用此应用来运行他们的业务.这是一场真正的灾难性失败.
我改变的唯一与iCloud相关的事情是将键值存储添加到iCloud.核心数据代码保持完全相同,模型版本相同(无迁移)等.
在我的测试中,一切都很美妙!但令我沮丧的是,用户报告说,当他们打开更新的应用程序时,他们的数据不再存在.
这可能是什么原因?
请在下面找到我的托管对象模型和持久性存储的代码.如果您还需要其他任何东西来评估问题,请告诉我.
- (NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext_ != nil) {
return managedObjectContext_;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext_ = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[managedObjectContext_ performBlockAndWait:^{
[managedObjectContext_ setPersistentStoreCoordinator:coordinator];
if (useICloud) {
[managedObjectContext_ setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mergeiCloud:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:coordinator];
}
}];
}
return managedObjectContext_;
}
Run Code Online (Sandbox Code Playgroud)
和
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator_ != nil) {
return persistentStoreCoordinator_;
}
NSMutableDictionary …Run Code Online (Sandbox Code Playgroud) 我不小心在CloudKit中创建了一个新的容器,当我打开仪表板时,它真的很烦人.有什么建议删除吗?在developer.apple.com上,我没有看到容器的删除按钮.
有没有人在Xcode 6和iOS 8上获得iCloud核心数据同步设置?(希望这不是一个重复的帖子)
iCloud核心数据存储选项在哪里?
我记得Core Data有一个名为Core Data storage的额外存储选项,但现在在Xcode 6中,当我在Xcode 6中启用iCloud切换时,它似乎只显示键值和文档存储.
到目前为止,我不知道我是否正确设置了Core Data iCloud.
Xcode似乎已在iOS Developer Portal中设置了iCloud容器:
iCloud.com.xxxxxx.xxxxxxxx (note: I've replaced the actual strings with xxxx here)
Run Code Online (Sandbox Code Playgroud)
我的Xcode 6 iCloud"服务"列表显示旁边没有刻度:
我们现在应该使用哪一个,因为它没有将"核心数据"列为存储选项?
在"服务"正下方的"容器"中,它显示以下灰色选项:
我无法选择任何选项,它似乎迫使我"使用默认容器".
最后,Xcode似乎显示为:
因此,通过Xcode自己的自动化流程,它为我设置了一切.
好的,所以我四处阅读并注意到这里写的iCloud堆栈:
https://github.com/mluisbrown/iCloudCoreDataStack
我已经采取了必要的代码并尝试适应我的核心数据管理器单例:
+ (id)sharedModel;
+ (ALAssetsLibrary *)sharedLibrary;
@property (nonatomic, readonly) NSManagedObjectContext *mainContext;
@property (nonatomic, readonly) NSPersistentStoreCoordinator *storeCoordinator;
- …Run Code Online (Sandbox Code Playgroud) 我将开始更新这个,以帮助那些寻求使用它作为他们自己的个人代码的参考.
最新更新
另一个有助于正确设置的补充
@property (nonatomic, readwrite) BOOL unlocked;到AppDelegate.h
和@synthesize unlocked;到AppDelegate.m.然后我改变了我的-
(NSPersistentStoreCoordinator *)persistentStoreCoordinator方法以及我的- (void)mergeChangesFrom_iCloud方法,两者都将在下面显示(在持久存储设置的中间和iCloud合并方法的底部).本质上,我告诉应用程序阻止iCloud合并数据,直到应用程序设置其持久存储.否则,您将看到应用程序因无法读取的故障而崩溃.以下是我设置persistentStoreCoordinator的方法:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
// here is where you declare the persistent store is not prepared;
self.unlocked = NO;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Maintain_My_Car.sqlite"];
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *options = …Run Code Online (Sandbox Code Playgroud) 我试图在(真实)设备和模拟器之间测试我的应用程序的iCloud同步功能,但我似乎无法登录到iCloud.当我转到Settings-> iCloud并输入我的帐户详细信息时,它就会卡在'验证'上.但是,如果我输入错误的详细信息,它会按预期显示无效的密码提示.
有人得到了解决方案吗?
我已经有一个iPhone应用程序将数据存储在本地文档文件夹中的文件中.现在我了解了iCloud技术,我的第一个问题是:当有时我检查新版本时,有没有办法将iCloud用作目录?
我的意思是:我可以避免使用UIDocument,文件协调员和文件演示者吗?我只想知道是否可以将iCloud视为特殊文件夹,只使用NSFileManager来推送和检索文件.
最后注意:我不使用Core Data或任何数据库,我只有一个数据文件.
编辑:
我已经阅读了官方的Apple iCloud文档,所以不要将我链接到他们.我只需要一些代码示例.