我一直试图创建一个简单的UIManagedDocument库样式应用程序(保存到iCloud的单独文档)非常失败.
我对以下内容感到困惑:
难道我的子类UIManagedDocument,并成立了persistentStoreCoordinator,ManagedObjectModel与ManagedObjectContext这个子类中,或者这些应该是内部配置的AppDelegate(如果是的话,我怎么去刷新persistentStoreCoordinator看新的文件-看来,一旦已经读了persistentStore这我不能让它读取新的持久存储)?
我正在使用Justin Driscoll在Core Data上使用单个共享UIManagedDocument实现.我的iphone应用程序中的一切都很好,直到我将它移动到iPad故事板和ipad应用程序的splitview控制器.问题是openwithCompletionHandler被调用两次,一次来自viewDidLoad中的主视图,另一次是我的详细视图viewWillLoad.这些调用是快速连续的,因为当对单例的performWithDocument方法(下面)进行第二次调用时,文档仍然在UIDocumentStateClosed中,应用程序崩溃.我查看了e_x_p对iOS5.1后的回答:同步任务(等待完成)但@sychronized在这种情况下不起作用,因为下面的performWithDocument是在同一个线程上调用的.我如何防止多次调用openwithCompletionHandler?我能想到防止这种情况的唯一方法是暂停执行上面的一个调用,直到我确定UIDocumentStateNormal为true然后释放.这虽然会冻结主要的UI线程,这是不好的.尽管如此,如果没有冻结用户界面,最好的办法是什么呢?
从UIManagedDocumentSingleton代码:
- (void)performWithDocument:(OnDocumentReady)onDocumentReady
{
void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success)
{
onDocumentReady(self.document);
};
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]])
{
//This should never happen*******************
[self.document saveToURL:self.document.fileURL
forSaveOperation:UIDocumentSaveForCreating
completionHandler:OnDocumentDidLoad];
} else if (self.document.documentState == UIDocumentStateClosed) {
[self.document openWithCompletionHandler:OnDocumentDidLoad];
} else if (self.document.documentState == UIDocumentStateNormal) {
OnDocumentDidLoad(YES);
}
}
Run Code Online (Sandbox Code Playgroud) Apple文档说我们需要注册NSUbiquityIdentityDidChangeNotification并比较当前的iCloud令牌和之前存储的令牌,NSUserDefaults以检测用户是否从文档和数据设置禁用了iCloud 或切换到另一个iCloud帐户.
我使用标准UIManagedDocument,我的目标是iOS 7,因此后备存储由CoreData自动处理.
我发现用户启用/禁用iCloud或切换到其他帐户后,我不明白应该怎么做.我应该迁移持久性商店吗?或者我应该在之后迁移它NSPersistentStoreCoordinatorStoresDidChangeNotification吗?或者我应该永远不会迁移它,因为所有内容都由CoreData处理?
几次观看WWDC 2013 207视频之后,我认为这将由Core Data自动处理,但我发现如果我从iCloud支持开始,然后我从文档和数据设置中关闭它并插入新数据,那么我切换回来iCloud开启,我以两个不同的数据集结束.
我希望如果我发现用户禁用了iCloud,那么本地数据库应该包含最后一次更改,直到启用iCloud,并且只有从这一点开始,一切都应该停止同步,直到iCloud再次启用.
在WWDC 2013 207视频中,在Melissa演示中,我还注意到一个方法[self migrateBack]之后调用了一个方法NSPersistentStoreCoordinatorStoresDidChangeNotification,这让我感到困惑,因为幻灯片只显示我们应该在这里保存我们的上下文并刷新UI,他们没有表明我们应该迁移任何东西:
**Account Changes Now**
NSPersistentStoreCoordinatorStoresWillChangeNotification
[NSManagedObjectContext save:]
[NSManagedObjectContext reset:]
NSPersistentStoreCoordinatorStoresDidChangeNotification
[NSManagedObjectContext save:]
Run Code Online (Sandbox Code Playgroud) 我已经看过如何使用块在我的整个应用程序共享的每个磁盘上创建一个全局UIManagedDocument实例?但我真的不明白.
我想要实现的是,整个应用程序应该只有一个UIManagedDocument - 一个核心数据库.不同的对象应该调用一个方法并获得唯一的UIManagedDocument.
我使用一个带有类方法的辅助类:
+ (UIManagedDocument *)getsharedDatabase:(NSString *)databaseName
{
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:databaseName];
// url is now "<Documents Directory>/<databaseName>"
if (![[NSFileManager defaultManager] fileExistsAtPath:[url absoluteString]])
{
// does not exist on disk, so create one
UIManagedDocument *managedDocument = [[UIManagedDocument alloc] initWithFileURL:url];
return managedDocument;
}
else
{
UIManagedDocument *managedDocument = **?????**
return managedDocument;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在问号中看到的那样,我不知道如何获取现有文件.我检查了UIManagedDocument类引用但找不到它.
你能帮我吗?提前谢谢了.
编辑 我想知道...单身方法怎么样,如:
+ (UIManagedDocument *) sharedDatabase
{
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] …Run Code Online (Sandbox Code Playgroud) 我正在开发我的第一个“iCloud 应用程序”。我浏览了 Apple 文档和斯坦福大学视频,但我仍然很难理解 iCloud 的“大局”。
我的目标是创建一个“库风格”应用程序(这是 Apple 的术语,指的是具有“单个核心数据堆栈、单个持久性存储协调器和单个持久性存储”的应用程序),如员工示例。
在斯坦福大学视频之后,我使用 UIMangedDocument 来设置所有核心数据内容并启用 iCloud 功能。UIMangedDocument 包含数据库并“存储在云中”。
这已经是我纠结的第一件事:“存储在云端”的真正含义是什么?
在我开始使用 iCloud 之前,我认为“在云中存储文档”意味着“在云中存储文档的副本”。我认为常规沙箱中会有我的文档的本地版本,并且云中会有该文档的副本。当本地文档发生更改时,这些更改也会传输到云版本。据我现在了解,这是不正确的(至少不完全正确)。我对吗?
要使用 iCloud,我要做的第一件事就是调用URLForUbiquityContainerIdentifier:。这将返回“iCloud URL”,这意味着云中文件夹的 URL。存储在该 URL 下的所有文件都将“存储在云端”,对吗?
我的第一个假设(本地文件+云中的副本)并不是完全错误的。事实上,存储在云中的任何文件都有“本地版本”和“云版本”。这是因为即使设备当前没有互联网连接,我也可以访问 iCloud URL 并将文件存储在该位置。但这只是 iCloud 框架的神奇之处,我不必担心。从我的角度来看,云只是一个特殊的文件夹,该文件夹中的任何文件或目录都存储在云中。仅当在设备设置中停用 iCloud 时,iCloud URL 才会为 NIL。是对的吗?
我遇到的第二件事是 iCloud 如何将更改同步到文档。假设设备 A 上的“TheApp”创建了一个 UIManagedDocument 并存储在云端。之后设备A离线。同时设备B上的TheApp访问该文档并添加一些数据(例如插入一些新员工或部门)。当设备 B 再次上线时,它将收到NSPersistentStoreDidImportUbiquitousContentChangesNotification ,并可以合并所有在文档的 ManagedObjectContext 上调用mergeChangesFromContextDidSaveNotification:来复制这些更改。
我无法确定合并更改是否真的有必要。如上所述,从我的角度来看,只有一个文档。如果这是真的,那么很高兴我收到有关更改的通知,但没有必要将这些更改复制到文档的“本地版本”,因为不存在“本地版本”之类的东西。这让我想到了 mergeChangesFromContextDidSaveNotification: 有什么好处的问题。
另一种情况与以前的情况相同(在设备 A 上创建文档,在设备 B 上更改...),但现在设备 A 不仅离线,而且在设备 B 上进行更改时 TheApp 完全关闭。在这种情况下,TheApp设备 A 上的文档再次启动后必须重新创建/重新打开该文档。在这种情况下应该发生什么?
我确实进行了一些测试,但结果并不总是相同。在某些情况下,文档以其“旧”版本开始,然后收到更改通知。在其他情况下,文档直接从新版本开始,并进行了所有更改。对于我的应用程序,第一种情况(从旧版本开始,接收更新通知)会更好,但我无法强制执行这种或另一种行为。这是它应该起作用的吗?
非常感谢!
这是我关于Stack Overflow的第一个问题,所以如果我打破任何礼仪,请原谅.我也是Objective-C/app创建的新手.
我一直在关注CS193P斯坦福课程,特别是CoreData讲座/演示.在Paul Hegarty的Photomania应用程序中,他以表格视图开始,并在后台填充数据,而不会中断UI流程.我一直在创建一个列出本地区域业务的应用程序(来自返回JSON数据的api).
我根据Paul的照片/摄影师课程创建了类别.类本身的创建不是问题,而是创建它们的地方.
A simplified data structure:
- Section
- Sub-section
- business
- business
- business
- business
- business
- business
Run Code Online (Sandbox Code Playgroud)
我的应用程序以带有几个按钮的UIViewController开始,每个按钮打开相应部分的tableview(这些都工作正常,我试图提供足够的信息,以便我的问题有意义).我调用一个帮助方法来创建/打开UIManagedDocument的URL,该URL基于这个问题.一旦应用程序运行,就会调用它,并且它会快速加载.
我有一个非常类似于Paul的fetchFlickrDataIntoDocument的方法:
-(void)refreshBusinessesInDocument:(UIManagedDocument *)document
{
dispatch_queue_t refreshBusinessQ = dispatch_queue_create("Refresh Business Listing", NULL);
dispatch_async(refreshBusinessQ, ^{
// Get latest business listing
myFunctions *myFunctions = [[myFunctions alloc] init];
NSArray *businesses = [myFunctions arrayOfBusinesses];
// Run IN document's thread
[document.managedObjectContext performBlock:^{
// Loop through new businesses and insert
for (NSDictionary *businessData in businesses) {
[Business businessWithJSONInfo:businessData inManageObjectContext:document.managedObjectContext]; …Run Code Online (Sandbox Code Playgroud) 我正在使用这个博客:http://www.adevelopingstory.com/blog/2012/03/core-data-with-a-single-shared-uimanageddocument.html为单身人士创建一个单身UIManagedDocument人士.这是相关的代码BetterDatabase
//In BetterDatabase
typedef void (^OnDocumentReady) (UIManagedDocument *document);
- (void)performWithDocument:(OnDocumentReady)onDocumentReady
{
void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success) {
onDocumentReady(self.document);
};
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]) {
[self.document saveToURL:self.document.fileURL
forSaveOperation:UIDocumentSaveForCreating
completionHandler:OnDocumentDidLoad];
} else if (self.document.documentState == UIDocumentStateClosed) {
[self.document openWithCompletionHandler:OnDocumentDidLoad];
} else if (self.document.documentState == UIDocumentStateNormal) {
OnDocumentDidLoad(YES);
}
}
//In other class
[[BetterDatabase sharedDocumentHandler] performWithDocument:^(UIManagedDocument * document) {
//Do stuff 1
//Do stuff 2
}];
Run Code Online (Sandbox Code Playgroud)
我的问题: 什么时候可以自动关闭UIManagedDocument?也就是说,文件是否可以在第1行和第2行之间关闭(通过OS/SDK)?如果用户最小化iPhone应用程序然后再次打开它会怎样?会UIManagedDocument被关闭吗?
另一种方法句话是这样的:将一个UIManagedDocument曾经亲密,而我仍然有很强的指向呢?
我正在关注有关iCloud和核心数据的WWDC 2013会议.我真的希望看到有任何新的视频UIManagedDocument或UIDocument.您可能还记得,这些类理论上提供了一种非常简单的方法来在本地和iCloud中使用(UIManagedDocument)或不使用CoreData(UIDocument)来保存数据.但是这些概念已经或者仍然存在一些非常烦人的基于系统的错误,特别是在设备之间同步数据时,请参见此处.
但是,没有视频覆盖UIManagedDocument/ UIDocument和iCloud主题.视频"Core Data和iCloud有什么新内容?" 仅介绍使用Core Data持久存储的经典方法,该存储由新API扩展以自动覆盖后备存储和同步.有什么事给任何信息UIManagedDocument/ UIDocument?他们是否放弃并将经典方法视为使用Core Data和iCloud同步应用程序的更好方法?
经过一些研究后,我仍然不确定何时/如何创建我的UIManagedDocument.
@interface ViewController ()
@property (strong, nonatomic) UIManagedDocument *document;
@end
@implementation ViewController
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentsDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSString *documentName = @"MyDocument";
NSURL *url = [documentsDirectory URLByAppendingPathComponent:documentName];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];
if (fileExists) {
[self.document openWithCompletionHandler:^(BOOL success) {
NSLog(@"Exsits dont create again");
if (success) [self documentIsReadyCreateAndObject];
if (!success) NSLog(@"cound not open document at %@", url);
}];
}
else {
// create it
[self.document saveToURL:url forSaveOperation:UIDocumentSaveForCreating …Run Code Online (Sandbox Code Playgroud) 我已经完成了斯坦福大学的课程,并按照讲座中的步骤设置了我的第一个应用程序和核心数据。大约是这样(我现在将代码转移到应用程序委托中):
- (void)setupFetchedResultsController
{
NSError *error = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]];
[self.budgetDatabase.managedObjectContext executeFetchRequest:request error:&error];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:self.budgetDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
-(void)useDocument
{
if(![[NSFileManager defaultManager]fileExistsAtPath:[self.budgetDatabase.fileURL path]]){
[self.budgetDatabase saveToURL:self.budgetDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
}];
} else if (self.budgetDatabase.documentState == UIDocumentStateClosed){
[self.budgetDatabase openWithCompletionHandler:^(BOOL success){
[self setupFetchedResultsController];
}];
} else if (self.budgetDatabase.documentState == UIDocumentStateNormal){
[self setupFetchedResultsController];
}
}
- (void)viewWillAppear:(BOOL)animated
{
//Initialize database
[super viewWillAppear:animated];
if(!self.budgetDatabase){
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentationDirectory …Run Code Online (Sandbox Code Playgroud) core-data ×8
ios ×5
objective-c ×5
icloud ×3
iphone ×3
ios5 ×1
ipad ×1
singleton ×1
uidocument ×1