我正在尝试将iCloud与我的iOS应用程序配合使用。我有应用程序在各个设备上工作,但当我添加iCloud时没有发生任何事情。我已经浏览了整个网络,只发现了一个我不理解的例子。我的应用程序是iOS 5.0并使用核心数据来存储页面。下面是我的应用程序委托和我在其中显示的视图。抱歉,对于iPhone开发人员缺乏了解。请帮忙。 http://goddess-gate.com/dc2/index.php/post/452
谢谢
如果有人知道/有一个iCloud + CoreData的完整工作项目我相信我可以搞清楚。现在我只有代码剪切它,我甚至不知道它们是如何被调用的......如果我有一个完整的项目,我可以逐步完成它,所以我可以完全理解它是如何工作的。
问题是我不认为有任何东西被调用用数据更新视图,我不相信它是将它发送到云但我不知道该叫什么...
PageFlipperAppDelegate.h
#import <UIKit/UIKit.h>
#import "PageView.h"
#import "SlideShowViewController.h"
#import "PagesCollectionViewController.h"
#import "UiWindowSubclass.h"
@interface PageFlipperAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, retain, readonly) PagesCollectionViewController *collectionViewController;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
@end
PageFlipperAppDelegate.m
#import "PageFlipperAppDelegate.h"
@implementation PageFlipperAppDelegate
@synthesize window;
@synthesize managedObjectContext, managedObjectModel, persistentStoreCoordinator,collectionViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
[NSThread sleepForTimeInterval:2.75];
collectionViewController = [[PagesCollectionViewController alloc] initWithManagedObjectContext:[self managedObjectContext]];
[(UINavigationController *)[[self window] rootViewController] pushViewController:collectionViewController animated:NO];
[collectionViewController release];
[[self window] makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
//stopping timer since we're going to background
// [(UiWindowSubclass *)self.window stopTimer];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application { [self saveContext]; }
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application { [self saveContext];
}
- (void)dealloc
{
[window release];
[managedObjectContext release];
[managedObjectModel release];
[persistentStoreCoordinator release];
[super dealloc];
}
- (void)awakeFromNib
{
}
- (void)saveContext
{
NSError *error = nil;
if ([self managedObjectContext])
{
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext
{
if (managedObjectContext != nil)
{
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
//if (IOS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0")) {
NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[moc performBlockAndWait:^{
[moc setPersistentStoreCoordinator: coordinator];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeChangesFrom_iCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator];
}];
managedObjectContext = moc;
}
return managedObjectContext;
}
/**
Returns the managed object model for the application.
If the model doesn't already exist, it is created from the application's model.
*/
- (NSManagedObjectModel *)managedObjectModel
{
if (!managedObjectModel)
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"PageFlipper" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return managedObjectModel;
}
/**
Returns the persistent store coordinator for the application.
If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator != nil)
{
return persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"PageFlipper.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];
// Migrate datamodel
NSDictionary *options = nil;
// this needs to match the entitlements and provisioning profile
NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:@"G88FQ4WK29.com.brandonsdesigngroup.3Doodles"];
NSString* coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"data"];
if ([coreDataCloudContent length] != 0) {
// iCloud is available
cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];
options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
@"3Doodles.store", NSPersistentStoreUbiquitousContentNameKey,
cloudURL, NSPersistentStoreUbiquitousContentURLKey,
nil];
} else {
// iCloud is not available
options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
}
NSError *error = nil;
[psc lock];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
[psc unlock];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"asynchronously added persistent store!");
[[NSNotificationCenter defaultCenter] postNotificationName:@"RefetchAllDatabaseData" object:self userInfo:nil];
});
});
return persistentStoreCoordinator;
}
- (void)mergeiCloudChanges:(NSNotification*)note forContext:(NSManagedObjectContext*)moc {
[moc mergeChangesFromContextDidSaveNotification:note];
NSNotification* refreshNotification = [NSNotification notificationWithName:@"RefreshAllViews" object:self userInfo:[note userInfo]];
[[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
}
- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {
NSManagedObjectContext* moc = [self managedObjectContext];
// this only works if you used NSMainQueueConcurrencyType
// otherwise use a dispatch_async back to the main thread yourself
[moc performBlock:^{
[self mergeiCloudChanges:notification forContext:moc];
}];
}
#pragma mark - Application's Documents directory
/**
Returns the URL to the application's Documents directory.
*/
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
@end
viewController.h
#import <Foundation/Foundation.h>
#import "CollectionViewController.h"
#import "SlideShowViewController.h"
#import "PagesDataSource.h"
#import "PageView.h"
#import "PageViewController.h"
#import "PrototypeView.h"
#import "QuickStart.h"
@interface PagesCollectionViewController : CollectionViewController<quickStartDismiss,NSFetchedResultsControllerDelegate>
{
PagesDataSource *dataSource;
PageViewController *viewController;
@private NSFetchedResultsController *fetchedResultsController__ ;
@private NSManagedObjectContext *managedObjectContext__;
}
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
- (IBAction)add:(id)sender;
-(void)setShadowAndColor;
-(void)playSlideShow;
@property (nonatomic, readwrite, assign) BOOL editMode;
@end
@interface PageView (CollectionViewItem)
- (void)setRepresentedObject:(PVPage *)representedObject;
- (PVPage *)representedObject;
-(void)didHoldItem;
-(void)duplicatePage;
@end
@interface PushController : UIViewController
{}
@end
@interface toolBar : UIToolbar
@end
viewController.m
#import "PagesCollectionViewController.h"
#import "PageFlipperAppDelegate.h"
@implementation toolBar
- (void)drawRect:(CGRect)rect {}
@end
@implementation PagesCollectionViewController
@synthesize editMode;
@synthesize fetchedResultsController=__fetchedResultsController;
@synthesize managedObjectContext=__managedObjectContext;
-(void)viewWillAppear:(BOOL)animated{
if (![[NSUserDefaults standardUserDefaults] integerForKey:@"integerKey"]) {
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:@"integerKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
QuickStart*stickieViewController = [[[QuickStart alloc]init]autorelease];
stickieViewController.delegate = self;
stickieViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:stickieViewController animated:YES];
}
[[self navigationController] setNavigationBarHidden:NO animated:NO];
[[self navigationController] setToolbarHidden:NO animated:NO];
[[[self navigationController] toolbar] setBarStyle:UIBarStyleBlackTranslucent];
[self setToolbarItems:[NSArray arrayWithObjects:
[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease],
[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(playSlideShow)]autorelease],
[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease],
nil]];
[(CollectionView*)[self view] setCanReloadData:YES];
[(CollectionView*)[self view]layoutSubviews];
}
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil)
{
return __fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Page" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptorName = [[NSSortDescriptor alloc] initWithKey:@"<sort key>" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptorName, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"<section name key path>" cacheName:@"<cache name>"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptorName release];
[sortDescriptors release];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __fetchedResultsController;
}
// because the app delegate now loads the NSPersistentStore into the NSPersistentStoreCoordinator asynchronously
// we will see the NSManagedObjectContext set up before any persistent stores are registered
// we will need to fetch again after the persistent store is loaded
- (void)reloadFetchedResults:(NSNotification*)note {
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
if (note) {
[(CollectionView*)[self view] setCanReloadData:YES];
[(CollectionView*)[self view]layoutSubviews];
}
}
-(void) playSlideShow{
SlideShowViewController *slideShowViewController = [[[SlideShowViewController alloc] init]autorelease];
NSMutableArray *tempArrayOfImages = [[[NSMutableArray alloc] init]autorelease];
for (int i = 0; i < [[dataSource pages]count]; i++) {
if ([[[dataSource pages] objectAtIndex:i] thumbnail] != nil) {
[tempArrayOfImages addObject: [[[dataSource pages] objectAtIndex:i] thumbnail]];
}
}
[[self navigationController] pushViewController:slideShowViewController animated:YES];
[slideShowViewController setImagesInImageViewer:tempArrayOfImages];
}
-(void)dismissQuickStart{
[self dismissModalViewControllerAnimated:YES];
}
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
{
if ((self = [super initWithNibName:@"CollectionView" bundle:nil]))
{
if (editMode == NO) {
[self finishEditToolBars];
}
[self setTitle:@"Doodles"];
viewController = [[PageViewController alloc] initWithManagedObjectContext:managedObjectContext];
dataSource = [[PagesDataSource alloc] initWithManagedObjectContext:managedObjectContext];
CGSize itemViewMarginSize = CGSizeMake(25.0, 0.0);
[(CollectionView *)[self view] setItemViewMarginSize:itemViewMarginSize];
PrototypeView *pro = [[[PrototypeView alloc] init] autorelease];
[(CollectionView *)[self view] setItemViewPrototype:pro];
[(CollectionView *)[self view] setFlowDirection:CVFlowDirectionVertical];
[(CollectionView *)[self view] setItemViewFrameSize:CGSizeMake(([(CollectionView *)[self view] bounds].size.width - 3*itemViewMarginSize.width)/3.4, ([(CollectionView *)[self view] bounds].size.height - 3*itemViewMarginSize.height)/3.6)];
[self setShadowAndColor];
}
return self;
}
-(void)setShadowAndColor{
CollectionView *collectionView = (CollectionView *)[self view];
[collectionView setShadowColor:[UIColor blackColor]];
[collectionView setShadowRadius:6.0f];
[collectionView setShadowOpacity:0.5f];
}
- (void)add:(id)sender
{
[dataSource add:sender];
CollectionView *collectionView = (CollectionView *)[self view];
// [collectionView reloadData];
// [collectionView scrollItemIndexToVisible:[self countOfItemsInCollectionView:collectionView]-1 animated:NO];
[collectionView.dataDelegate collectionView:collectionView didSelectItemAtIndex:[self countOfItemsInCollectionView:collectionView]-1];
//CollectionViewController *c;
// [[c transitionToDetailViewController:[c collectionView:self detailViewControllerForItemAtIndex:(NSUInteger)[self countOfItemsInCollectionView:collectionView]-1] forItemView:[itemViews objectForKey:[NSString stringWithFormat:@"%u", [self countOfItemsInCollectionView:collectionView]-1]]]];
// [c transitionToDetailViewController:self forItemView:collectionView.itemViews;
editMode = NO;
//collectionView.canUpdateLayout = YES;
collectionView.canReloadData = YES;
[(CollectionView*)[self view]layoutSubviews];
}
- (NSUInteger)countOfItemsInCollectionView:(CollectionView *)collectionView { return [[dataSource pages] count]; }
- (id)collectionView:(CollectionView *)collectionView representedObjectAtIndex:(NSUInteger)itemIndex {
return [[dataSource pages] objectAtIndex:itemIndex];
}
- (void)collectionView:(CollectionView *)collectionView didSelectItemAtIndex:(NSUInteger)itemIndex
{
if (editMode == YES) {
[collectionView yellowdidSelectItemAtIndex:itemIndex];
// NSLog(@"edit");
}else{
PVPage *selectedPage = [[[dataSource pages] objectAtIndex:itemIndex]autorelease];
PageView *pageView = [[[PageView alloc] init] autorelease];
[pageView setRepresentedPage:selectedPage];
// UIImage *i = [UIImage imageWithData: [[pageView representedPage] thumbnail]];
// UIImageView *ii = [[[UIImageView alloc] initWithImage:i]autorelease];
[viewController setView:pageView];
// [(PageView*)[viewController view] setBackgroundStrokes:ii];
//NSLog(@"selected page %@",selectedPage);
// [[[self navigationController] toolbar] setHidden:YES];
// [[[self navigationController] navigationBar] setHidden:YES];
// [[[self tabBarController] tabBar] setHidden:YES];
PageFlipperAppDelegate *appDelegate = (PageFlipperAppDelegate *)[[UIApplication sharedApplication] delegate];
// [(UiWindowSubclass *)appDelegate.window startTimer];
[(UINavigationController *)[(UiWindowSubclass*)[appDelegate window] rootViewController] pushViewController:viewController animated:YES];
// viewController = nil;
// [[self navigationController] setToolbarHidden:NO];
}
}
- (BOOL)collectionView:(CollectionView *)collectionView canDeleteItemAtIndex:(NSUInteger)itemIndex {
NSLog(@"itemIndex %u",itemIndex);
return YES;
}
- (void)collectionView:(CollectionView *)collectionView didDeleteItemAtIndex:(NSUInteger)itemIndex
{
[dataSource removePageAtIndex:itemIndex];
}
-(void)trash{
// NSLog(@"trash");
[(CollectionView *)[self view] trashitems];
}
-(void)done{
[(CollectionView *)[self view] yellowdidSelectItemAtIndexUndo];
[(CollectionView *)[self view] shakedidRemoveSelectItemAtIndex];
[(CollectionView *)[self view] donereset];
[self finishEditToolBars];
}
-(void) finishEditToolBars{
[[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(add:)] autorelease]];
[[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(didHoldItem)] autorelease]];
editMode = NO;
}
-(void)duplicatePage{
NSArray *tempArray = [[[(CollectionView*)[self view] selectedItemsArray]copy]autorelease];
// for (int i =0; i<[[(CollectionView*)[self view] selectedItemsArray]count]; i++) {
// [(CollectionView *)[self view] yellowdidSelectItemAtIndex:i];
//
// }
[dataSource duplicatePage:[[[NSArray alloc] initWithArray:tempArray]autorelease]];
CollectionView *collectionView = (CollectionView *)[self view];
editMode = NO;
[self done];
// [(CollectionView *)[self view] yellowdidSelectItemAtIndexUndo];
collectionView.canReloadData = YES;
[collectionView layoutSubviews];
}
-(void)didHoldItem{
[[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done)] autorelease]];
// [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(trash)] autorelease]];
toolBar* tools = [[toolBar alloc] initWithFrame:CGRectMake(0, 0, 133, 44.01)];
tools.barStyle = UIBarStyleBlackTranslucent;
tools.opaque = NO;
//tools.backgroundColor = [UIColor clearColor];
// create the array to hold the buttons, which then gets added to the toolbar
NSMutableArray* buttons = [[NSMutableArray alloc] initWithCapacity:3];
// create a standard "add" button
UIBarButtonItem* bi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(trash)];
bi.style = UIBarButtonItemStyleBordered;
[buttons addObject:bi];
[bi release];
// create a spacer
bi = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
[buttons addObject:bi];
[bi release];
// create a standard "refresh" button
bi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemOrganize target:self action:@selector(duplicatePage)];
bi.style = UIBarButtonItemStyleBordered;
[buttons addObject:bi];
[bi release];
// stick the buttons in the toolbar
[tools setItems:buttons animated:NO];
[buttons release];
// and put the toolbar in the nav bar
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:tools] autorelease];
[tools release];
[(CollectionView*)[self view] setOldItemIndex:-1];
editMode = YES;
[(CollectionView*)[self view] setEditMode:YES];
[(CollectionView*)[self view] shakedidSelectItemAtIndex];
}
-(void)didReceiveMemoryWarning{
// NSLog(@"mem");
}
- (void)dealloc
{ [dataSource release],dataSource = nil;
[viewController release],viewController = nil;
[super dealloc];
}
-(void)viewDidAppear:(BOOL)animated{
[ (CollectionView*) [self view] setCanReloadData:YES];
[(CollectionView*) [self view] layoutSubviews];
}
-(void) viewDidLoad{
CollectionView *collectionView = (CollectionView *)[self view];
collectionView.canReloadData = YES;
[(CollectionView*)[self view]layoutSubviews];
editMode = NO;
collectionView.editMode = NO;
}
@end
答案 0 :(得分:4)
在Apple开发人员论坛上发布了iPhoneCoreDataRecipes示例代码,其中包含iCloud。
答案 1 :(得分:3)
您可以观看今年的WWDC 2012 Session 227讲座(您可以使用Apple Developer帐户自由访问这些视频),这将展示如何正确使用Core Data和iCloud,说明正确的应用程序架构,Core Data的方式和iCloud应该互相交谈,并通过一个完整的示例项目解释所有这些内容。
修改强>
该项目的完整资源仅供this page下所有注册的Apple开发人员使用。
答案 2 :(得分:2)
这是一个非常有争议的话题......我需要在我的下一个应用程序中添加带有Core Data的iCloud,但这有点难以启动。我什么也没做,但我发现这些文件非常有用:
答案 3 :(得分:2)
这不仅仅是有争议的,还没有充分发挥作用。如果您能够对样本进行编码,您可能会发现它只能偶尔使用。我希望我能写出它已经解决了,这就是你如何使用它 - 也许其他人可以,但截至2012年3月,我对此表示怀疑。
然而,编写示例代码以及开发站点中的其他代码是有趣且有益的,这样您就可以了解iCloud /核心数据的全部内容。
我们中的很多人都在努力巩固这一点。
您可能需要在Dox精彩网站上试用Ray Wenderlich's。但你最终可能会遇到同样的挫败感。有时它起作用,主要不起作用。
答案 4 :(得分:2)
Blackpixel已经提升了Core Data Recipes with iCloud to Github的版本。它可能比dev论坛中的版本有所改进。
我已经使用dev forums version并发现它有效,但需要一些时间来同步。阅读那里的评论主题(19页并计数),并决定它。