Xcode 6 iOS 8 iCloud核心数据设置

2020/12/16 18:12 · ios ·  · 0评论

有人在Xcode 6和iOS 8上获得过iCloud核心数据同步设置吗?(希望这不是重复的帖子)

iCloud Core数据存储选件到哪里去了?

我记得Core Data还有一个称为Core Data storage的额外存储选项,但是现在在Xcode 6中,当我在Xcode 6中启用iCloud切换时,它似乎仅显示键值和文档存储。

背景资料

  • 新的iPad应用
  • Xcode 6
  • 定位最低版本的iOS 7,但希望它也适用于iOS 8?(我们可以将iOS 8设置为最低)
  • 想要使用iCloud Core数据存储而不是键值存储或文档存储。
  • 在Simulator和iPad设备的``设置''>``iCloud''中登录了相同的Apple帐户
  • 我的配置文件用于对应用程序进行代码签名,已为开发和分发启用了iCloud(由Xcode自动启用)

我的设定

到目前为止,我不知道我是否已正确设置Core Data iCloud。

Xcode似乎已在iOS开发人员门户中设置了iCloud容器:

iCloud.com.xxxxxx.xxxxxxxx   (note: I've replaced the actual strings with xxxx here)

我的Xcode 6 iCloud“服务”列表在以下位置旁边没有任何刻度:

  • 键值存储
  • iCloud文件
  • CloudKit

由于它没有列出“核心数据”作为存储选项,因此我们现在应该使用哪一个?

在“服务”正下方的“容器”中,其显示为灰色的以下选项:

  • 使用默认容器(默认选中该容器)
  • 指定自定义容器
  • iCloud.com.xxxxxxxxxx.xxxxxxxxx(再次用xxxx代替真实标识符)

我无法选择任何选项,似乎迫使我“使用默认容器”。

最后,Xcode似乎在以下方面显示了滴答声:

  • 将“ iCloud”权利添加到您的应用ID
  • 将“ iCloud容器”权利添加到您的应用程序ID
  • 将“ iCloud”权利人添加到您的权利文件中
  • 链接CloudKit.framework

因此,通过Xcode自己的自动化流程,它可以为我设置一切。

参考代码

好的,所以我环顾四周,注意到这里写了一个iCloud堆栈:

https://github.com/mluisbrown/iCloudCoreDataStack

我已经采用了必要的代码,并尝试适应我的Core Data Manager单例:

DataManager.h文件

+ (id)sharedModel;
+ (ALAssetsLibrary *)sharedLibrary;

@property (nonatomic, readonly) NSManagedObjectContext *mainContext;
@property (nonatomic, readonly) NSPersistentStoreCoordinator *storeCoordinator;

- (NSString *)modelName;
- (NSString *)pathToModel;
- (NSString *)storeFilename;
- (NSString *)pathToLocalStore;


#pragma mark - Entity Fetching Methods -

-(NSArray *)fetchEntityOfType:(NSString *)entityType UsingPredicated:(NSPredicate *)predicate sortBy:(NSString *)sortKey ascendingOrder:(BOOL)ascendingOrder;

DataManager.m文件

@property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
- (NSString *)documentsDirectory;

@end

@implementation MLSAlbumsDataModel
@synthesize managedObjectModel = _managedObjectModel;
@synthesize storeCoordinator = _storeCoordinator;
@synthesize mainContext = _mainContext;

+ (id)sharedModel {
    static MLSAlbumsDataModel *__instance = nil;
    if (__instance == nil) {
        __instance = [[MLSAlbumsDataModel alloc] init];
    }
    return __instance;
}

+ (ALAssetsLibrary *)sharedLibrary {
    static ALAssetsLibrary *__instance = nil;
    if (__instance == nil) {
        __instance = [[ALAssetsLibrary alloc] init];
    }
    return __instance;

}

- (NSString *)modelName {
    return @"Albums";
}

- (NSString *)pathToModel {
    return [[NSBundle mainBundle] pathForResource:[self modelName] ofType:@"momd"];
}

- (NSString *)storeFilename {
    return [[self modelName] stringByAppendingPathExtension:@"sqlite"];
}

- (NSString *)pathToLocalStore {
    return [[self documentsDirectory] stringByAppendingPathComponent:[self storeFilename]];
}

- (NSString *)documentsDirectory {
    NSString *documentsDirectory = nil;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    documentsDirectory = [paths objectAtIndex:0];
    return documentsDirectory;
}

- (NSManagedObjectContext *)mainContext {
    if(_mainContext == nil) {
        _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        _mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;        

        // setup persistent store coordinator

        DLog(@"SQLITE STORE PATH: %@", [self pathToLocalStore]);
        NSURL *storeURL = [NSURL fileURLWithPath:[self pathToLocalStore]];


        //_mainContext.persistentStoreCoordinator = [self storeCoordinator];

        _mainContext.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];



        __weak NSPersistentStoreCoordinator *psc = self.mainContext.persistentStoreCoordinator;

        // iCloud notification subscriptions
        NSNotificationCenter *dc = [NSNotificationCenter defaultCenter];
        [dc addObserver:self
               selector:@selector(storesWillChange:)
                   name:NSPersistentStoreCoordinatorStoresWillChangeNotification
                 object:psc];

        [dc addObserver:self
               selector:@selector(storesDidChange:)
                   name:NSPersistentStoreCoordinatorStoresDidChangeNotification
                 object:psc];

        [dc addObserver:self
               selector:@selector(persistentStoreDidImportUbiquitousContentChanges:)
                   name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
                 object:psc];

        NSError* error;
        // the only difference in this call that makes the store an iCloud enabled store
        // is the NSPersistentStoreUbiquitousContentNameKey in options. I use "iCloudStore"
        // but you can use what you like. For a non-iCloud enabled store, I pass "nil" for options.

        // Note that the store URL is the same regardless of whether you're using iCloud or not.
        // If you create a non-iCloud enabled store, it will be created in the App's Documents directory.
        // An iCloud enabled store will be created below a directory called CoreDataUbiquitySupport
        // in your App's Documents directory
        [self.mainContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                                           configuration:nil
                                                                            URL:storeURL
                                                                        options:@{ NSPersistentStoreUbiquitousContentNameKey : @"iCloudStore" }
                                                                          error:&error];
        if (error) {
            NSLog(@"error: %@", error);
        }

        _storeCoordinator = self.mainContext.persistentStoreCoordinator;

    }
    return _mainContext;
}

- (NSManagedObjectModel *)managedObjectModel {
    if(_managedObjectModel == nil) {
        NSURL *storeURL = [NSURL fileURLWithPath:[self pathToModel]];
        _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:storeURL];
    }
    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)storeCoordinator {
    if (_storeCoordinator == nil) {
        // -----------------------------------------------------------------------------------------------------------------------------
        // Code moved to managed object context code above
        // -----------------------------------------------------------------------------------------------------------------------------
        /*

        DLog(@"SQLITE STORE PATH: %@", [self pathToLocalStore]);
        NSURL *storeURL = [NSURL fileURLWithPath:[self pathToLocalStore]];

        NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
        NSError *error = nil;




        if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
            NSDictionary *userInfo = [NSDictionary dictionaryWithObject:error forKey:NSUnderlyingErrorKey];
            NSString *reason = @"Could not create persistent store";
            NSException *exc = [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:userInfo];
            @throw exc;
        }

        _storeCoordinator = psc;

         */

    }
    return _storeCoordinator;
}


#pragma mark - iCloud Related Methods -

// Subscribe to NSPersistentStoreDidImportUbiquitousContentChangesNotification
- (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification*)note
{
    NSLog(@"%s", __PRETTY_FUNCTION__);
    NSLog(@"%@", note.userInfo.description);

    NSManagedObjectContext *moc = self.mainContext;
    [moc performBlock:^{
        [moc mergeChangesFromContextDidSaveNotification:note];

        DLog(@"NSPersistentStoreDidImportUbiquitousContentChangesNotification executed");
        /*

        // you may want to post a notification here so that which ever part of your app
        // needs to can react appropriately to what was merged.
        // An exmaple of how to iterate over what was merged follows, although I wouldn't
        // recommend doing it here. Better handle it in a delegate or use notifications.
        // Note that the notification contains NSManagedObjectIDs
        // and not NSManagedObjects.
        NSDictionary *changes = note.userInfo;
        NSMutableSet *allChanges = [NSMutableSet new];
        [allChanges unionSet:changes[NSInsertedObjectsKey]];
        [allChanges unionSet:changes[NSUpdatedObjectsKey]];
        [allChanges unionSet:changes[NSDeletedObjectsKey]];

        for (NSManagedObjectID *objID in allChanges) {
            // do whatever you need to with the NSManagedObjectID
            // you can retrieve the object from with [moc objectWithID:objID]
        }

        */

    }];
}

// Subscribe to NSPersistentStoreCoordinatorStoresWillChangeNotification
// most likely to be called if the user enables / disables iCloud
// (either globally, or just for your app) or if the user changes
// iCloud accounts.
- (void)storesWillChange:(NSNotification *)note {
    NSManagedObjectContext *moc = self.mainContext;
    [moc performBlockAndWait:^{
        NSError *error = nil;
        if ([moc hasChanges]) {
            [moc save:&error];
        }

        [moc reset];
    }];

    // now reset your UI to be prepared for a totally different
    // set of data (eg, popToRootViewControllerAnimated:)
    // but don't load any new data yet.

    [[NSNotificationCenter defaultCenter] postNotificationName:@"notifCoreDataStoreWillChange" object:nil];

    DLog(@"storeWillChange notification fire");
}

// Subscribe to NSPersistentStoreCoordinatorStoresDidChangeNotification
- (void)storesDidChange:(NSNotification *)note
{
    // here is when you can refresh your UI and
    // load new data from the new store


    [[NSNotificationCenter defaultCenter] postNotificationName:@"notifCoreDataStoreDidChange" object:nil];

    DLog(@"storeDidChange notification fire");
}



#pragma mark - Entity Fetching Methods -

-(NSArray *)fetchEntityOfType:(NSString *)entityType UsingPredicated:(NSPredicate *)predicate sortBy:(NSString *)sortKey ascendingOrder:(BOOL)ascendingOrder
{
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityType inManagedObjectContext:[[MLSAlbumsDataModel sharedModel] mainContext]];


    NSSortDescriptor *sortDescriptor = nil;

    if(sortKey)
    {
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:ascendingOrder];
    }
    else
    {
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"updatedAt" ascending:ascendingOrder];
    }


    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    request.entity = entityDescription;

    if(predicate)
    {
        request.predicate = predicate;
    }

    request.sortDescriptors = @[sortDescriptor];

    NSError *error = nil;

    NSArray *results = [[[MLSAlbumsDataModel sharedModel] mainContext] executeFetchRequest:request error:&error];

    if(results == nil)
    {
        DLog(@"Error getting entity of type '%@' using predicate '%@', sortKey '%@' ascendingOrder %d", entityType, predicate, sortKey, ascendingOrder);
    }

    return results;
}

我的观察

我试图在iPad Simulator(我相信它是iOS 8模拟器)和运行iOS 7.x的iPad设备上运行该应用程序

我在模拟器上用用户输入的名称创建了一个相册,但是没有看到iPad设备显示新创建的相册。我也尝试过颠倒角色,iPad设备创建,iOS模拟器也没有结果。

我确实看到了我的日志消息:

storeDidChange notification fire

SQLITE STORE PATH: /Users/xxxxxxx/Library/Developer/CoreSimulator/Devices/3DC17576-92E9-4EAF-B77A-41340AE28F92/data/Containers/Data/Application/E51085CE-3772-4DF1-A503-1C243497091A/Documents/Albums.sqlite

如果我在模拟器中最小化该应用程序并再次打开它(而无需按Xcode中的“停止”按钮),则会看到以下消息:

-[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity:  nobody~sim301AE3E8-16B2-5A08-917D-7B55D1879BE4:iCloudStore
Using local storage: 1

我读到“使用本地存储:0”是理想的状态?并且1表示本地设备数据存储而不是iCloud数据存储。

当我创建专辑时,保存它,停止模拟器,然后再次启动该应用程序,我的专辑消失了,但是在我创建新专辑后,先前的所有专辑立即又神奇地再次出现。有点奇怪 如果我不使用iCloud并将代码还原为以前的设置,则可以创建并查看专辑,无论是否最小化我的应用程序或重新启动应用程序,但我没有所需的iCloud同步。

我在任何地方犯过任何错误吗?

抱歉,很长的帖子,但是有人让iCloud适用于iOS 8和Xcode 6吗?

我真的可以使用一些帮助。

额外问题

1)iOS 8是否要求使用此容器标识符?(这是Xcode 6为我生成的):

com.apple.developer.icloud-container-identifiers

那不是iOS 7的样子吗?iOS 7更像:

com.apple.developer.ubiquity-container-identifiers

2)我需要一个iCloud Drive帐户才能运行吗?

超级困惑@ _ @

iOS 8解决方案:

好...然后... 我想我解决了。

新发现。浏览完此页面后:

http://www.tuaw.com/2014/09/17/psa-do-not-not-upgrade-to-icloud-drive-during-ios-8-installation/

它说:

iCloud Drive是Apple新增和改进的iCloud同步和文件存储功能,可让您在iOS 8设备和运行OS X 10 Yosemite的Mac之间共享文档。

因此,我决定硬着头皮将我的iCloud帐户升级到iCloud驱动器(免费升级)。

升级到iCloud驱动器并重新运行我的应用程序后,对Xcode 6进行了一些更改,现在可以正常使用了。

一些重要的注意事项:

  • iCloud Drive与以前的iCloud文档和数据存储不兼容。因此,如果要进行测试,请确保所有设备都使用iCloud驱动器和iOS 8。
  • 在启动应用程序后,模拟器似乎只同步一次,而设备则在每个间隔持续同步。不知道这是否是模拟器错误。也许我的配置不完美。
  • 首次尝试使用“使用默认容器”对我来说在模拟器中不起作用(但在它可以工作的设备上),也许需要删除该应用程序的先前副本并重新安装。首先尝试使用默认容器,看看它是否有效,否则,请阅读下面的要点。
  • 由于上述原因,我改为使用具有这种模式的Ubiquity容器:

    iCloud。$(CFBundleIdentifier)

所以像:

iCloud.com.xxxxxxxx.iCloudCoreDataDemo

其中“ xxxxxxxx”是我的公司名称标识符。

我通过登录iOS开发人员中心制作了上述iCloud容器,也许您只需按Xcode 6内的“ +”号,然后在其中输入一个即可,Xcode应该自动为您设置所有内容。

我用来测试它是否正常工作的代码块是:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.persistentStack = [[PersistentStack alloc] initWithStoreURL:self.storeURL modelURL:self.modelURL];
    self.managedObjectContext = self.persistentStack.managedObjectContext;

    NSURL *containerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:@"iCloud.com.xxxxxxxxxx.iCloudCoreDataDemo"];

    if(containerURL == nil)
    {
        NSLog(@"containerURL == nil");
    }
    else
    {
        NSLog(@"hurray?");
    }

    return YES;
}

如果看到“欢呼声”?那就很好了,您还应该在Xcode控制台输出中看到这种文本模式:

2014-10-07 17:37:23.196 iCloudCoreDataDemo[8104:130250] documentsDirectory = file:///Users/xxxxxxxx/Library/Developer/CoreSimulator/Devices/9FAFE881-13CA-4608-8BE6-728C793FAFFB/data/Containers/Data/Application/BC6CA07D-605A-4927-94AF-E9E21E204D2B/Documents/
2014-10-07 17:37:23.386 iCloudCoreDataDemo[8104:130250] storeDidChange
2014-10-07 17:37:23.390 iCloudCoreDataDemo[8104:130250] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity:  nobody~sim301AE3E8-16B2-5A08-917D-7B55D1879BE4:iCloudStore
Using local storage: 1
2014-10-07 17:37:23.402 iCloudCoreDataDemo[8104:130250] hurray?
2014-10-07 17:37:33.909 iCloudCoreDataDemo[8104:130250] storeWillChange
2014-10-07 17:37:33.933 iCloudCoreDataDemo[8104:130250] storeDidChange
2014-10-07 17:37:33.933 iCloudCoreDataDemo[8104:130330] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity:  nobody~sim301AE3E8-16B2-5A08-917D-7B55D1879BE4:iCloudStore
Using local storage: 0

请注意以下两行:

Using local storage: 1

后来变成:

Using local storage: 0

本地存储1表示它当前正在使用本地存储,而本地存储0表示它已将数据移至iCloud存储。

我希望这对其他所有人都有好处。

仅iOS 7解决方案:

好的,所以我刚刚发现了一些东西,并且设法使其适用于iOS 7我仍然没有想出如何在iOS 8中做到这一点,但我注意到了一些重要的事情。

在运行iOS 8.0.2的iPhone 5上,我不再在iCloud设置菜单中拥有“文档和数据”选项。

但是,在运行iOS 7的iPad上,我确实看到了“文档和数据”选项。

也许这就是为什么它不能在iOS 8上运行的原因,我们不再拥有文档和数据存储了?

无论如何,这就是我发现的仅适用于iOS 7的解决方案。

我在这里找到此页面

https://developer.apple.com/library/ios/documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html

其中一行说:

  • iCloud文档存储用于用户可见的基于文件的内容,Core Data存储或其他复杂的基于文件的内容。

果然,我进入了Xcode 6项目文件,并勾选了“ iCloud文档”选项。这使单选按钮变为灰色,但我仍将其保留在“使用默认容器”中。

我了解到的一件事是,我需要在appDelegate中初始化PersistentStack。以前,我尝试在+(id)sharedInstance方法内初始化持久性堆栈,但它导致iCloud仅在第一次同步,因此在初始加载和同步后,添加新记录之后就不会同步。

我重写了一个基本应用程序,并稍微修改了持久性堆栈:

应用程序Delegate.h

#import <UIKit/UIKit.h>
#import "PersistentStack.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (nonatomic, strong) NSManagedObjectContext* managedObjectContext;
@property (nonatomic, strong) PersistentStack* persistentStack;


@end

App Delegate.m

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.persistentStack = [[PersistentStack alloc] initWithStoreURL:self.storeURL modelURL:self.modelURL];
    self.managedObjectContext = self.persistentStack.managedObjectContext;

    return YES;
}

...

- (NSURL*)storeURL
{
    NSURL* documentsDirectory = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL];
    return [documentsDirectory URLByAppendingPathComponent:@"MyApp.sqlite"];
}

- (NSURL*)modelURL
{
    return [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"];
}

持久堆栈

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

#import "Book.h"
#import <UIKit/UIKit.h>

@interface PersistentStack : NSObject

+(id)sharedInstance;

- (id)initWithStoreURL:(NSURL *)storeURL modelURL:(NSURL *)modelURL;

@property (nonatomic,strong,readonly) NSManagedObjectContext *managedObjectContext;

#pragma mark - Regular Methods -

-(Book *)insertNewBookWithDate:(NSDate *)newDate;
-(void)deleteBook:(Book *)book;
-(NSArray *)fetchEntityOfType:(NSString *)entityType withPredicate:(NSPredicate *)predicate andSortKey:(NSString *)sortKey;

@end

持久堆栈

#import "PersistentStack.h"
#import "AppDelegate.h"

@interface PersistentStack ()

@property (nonatomic,strong,readwrite) NSManagedObjectContext* managedObjectContext;
@property (nonatomic,strong) NSURL* modelURL;
@property (nonatomic,strong) NSURL* storeURL;

@end

@implementation PersistentStack

+(id)sharedInstance
{
    static PersistentStack *sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

        sharedInstance = appDelegate.persistentStack;
    });

    return sharedInstance;
}

- (id)initWithStoreURL:(NSURL*)storeURL modelURL:(NSURL*)modelURL
{
    self = [super init];
    if (self) {
        self.storeURL = storeURL;
        self.modelURL = modelURL;
        [self setupManagedObjectContext];
    }
    return self;
}

- (void)setupManagedObjectContext
{
    self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
    self.managedObjectContext.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];


    //__weak NSPersistentStoreCoordinator *psc = self.managedObjectContext.persistentStoreCoordinator;

    // iCloud notification subscriptions
    NSNotificationCenter *dc = [NSNotificationCenter defaultCenter];
    [dc addObserver:self
           selector:@selector(storesWillChange:)
               name:NSPersistentStoreCoordinatorStoresWillChangeNotification
             object:self.managedObjectContext.persistentStoreCoordinator];

    [dc addObserver:self
           selector:@selector(storesDidChange:)
               name:NSPersistentStoreCoordinatorStoresDidChangeNotification
             object:self.managedObjectContext.persistentStoreCoordinator];

    [dc addObserver:self
           selector:@selector(persistentStoreDidImportUbiquitousContentChanges:)
               name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
             object:self.managedObjectContext.persistentStoreCoordinator];

    NSError* error;
    // the only difference in this call that makes the store an iCloud enabled store
    // is the NSPersistentStoreUbiquitousContentNameKey in options. I use "iCloudStore"
    // but you can use what you like. For a non-iCloud enabled store, I pass "nil" for options.

    // Note that the store URL is the same regardless of whether you're using iCloud or not.
    // If you create a non-iCloud enabled store, it will be created in the App's Documents directory.
    // An iCloud enabled store will be created below a directory called CoreDataUbiquitySupport
    // in your App's Documents directory
    [self.managedObjectContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                                       configuration:nil
                                                                                 URL:self.storeURL
                                                                             options:@{ NSPersistentStoreUbiquitousContentNameKey : @"iCloudStore" }
                                                                               error:&error];
    if (error) {
        NSLog(@"error: %@", error);
    }
}

- (NSManagedObjectModel*)managedObjectModel
{
    return [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL];
}

// Subscribe to NSPersistentStoreDidImportUbiquitousContentChangesNotification
- (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification*)note
{
    NSLog(@"%s", __PRETTY_FUNCTION__);
    NSLog(@"%@", note.userInfo.description);

    NSManagedObjectContext *moc = self.managedObjectContext;
    [moc performBlock:^{
        [moc mergeChangesFromContextDidSaveNotification:note];

        [[NSNotificationCenter defaultCenter] postNotificationName:@"notifiCloudStoreDidChange" object:nil];

        /*
        // you may want to post a notification here so that which ever part of your app
        // needs to can react appropriately to what was merged.
        // An exmaple of how to iterate over what was merged follows, although I wouldn't
        // recommend doing it here. Better handle it in a delegate or use notifications.
        // Note that the notification contains NSManagedObjectIDs
        // and not NSManagedObjects.
        NSDictionary *changes = note.userInfo;
        NSMutableSet *allChanges = [NSMutableSet new];
        [allChanges unionSet:changes[NSInsertedObjectsKey]];
        [allChanges unionSet:changes[NSUpdatedObjectsKey]];
        [allChanges unionSet:changes[NSDeletedObjectsKey]];

        for (NSManagedObjectID *objID in allChanges) {
            // do whatever you need to with the NSManagedObjectID
            // you can retrieve the object from with [moc objectWithID:objID]
        }
         */

    }];
}

// Subscribe to NSPersistentStoreCoordinatorStoresWillChangeNotification
// most likely to be called if the user enables / disables iCloud
// (either globally, or just for your app) or if the user changes
// iCloud accounts.
- (void)storesWillChange:(NSNotification *)note {

    NSLog(@"storeWillChange");

    NSManagedObjectContext *moc = self.managedObjectContext;

    //[moc performBlockAndWait:^{
    [moc performBlock:^{
        NSError *error = nil;
        if ([moc hasChanges]) {
            [moc save:&error];
        }

        [moc reset];
    }];

    // now reset your UI to be prepared for a totally different
    // set of data (eg, popToRootViewControllerAnimated:)
    // but don't load any new data yet.
}

// Subscribe to NSPersistentStoreCoordinatorStoresDidChangeNotification
- (void)storesDidChange:(NSNotification *)note {
    // here is when you can refresh your UI and
    // load new data from the new store

    NSLog(@"storeDidChange");

    [[NSNotificationCenter defaultCenter] postNotificationName:@"notifiCloudStoreDidChange" object:nil];
}

#pragma mark - Regular Methods -

-(Book *)insertNewBookWithDate:(NSDate *)newDate
{
    Book *newBook = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:self.managedObjectContext];

    newBook.bookName = @"Book";
    newBook.publishDate = newDate;

    [self.managedObjectContext save:nil];

    return newBook;
}

-(void)deleteBook:(Book *)book
{
    [self.managedObjectContext deleteObject:book];

    [self.managedObjectContext save:nil];
}

-(NSArray *)fetchEntityOfType:(NSString *)entityType withPredicate:(NSPredicate *)predicate andSortKey:(NSString *)sortKey
{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityType inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    // Specify criteria for filtering which objects to fetch
    [fetchRequest setPredicate:predicate];
    // Specify how the fetched objects should be sorted
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey
                                                                   ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];

    NSError *error = nil;
    NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    if (fetchedObjects == nil)
    {
        NSLog(@"couldn't fetch entity of type '%@', error: %@", entityType, error.localizedDescription);
    }

    return fetchedObjects;
}

@end

我为类似的问题而苦苦挣扎。我会看见:

Using local storage: 1

但没有其他输出。如果我重新构建应用程序,我将得到类似以下内容:

Error adding store for new account:

需要注意的一件事是,只有先按iPhone上的“主页”按钮,然后重新打开应用程序,我才能获得此输出。

需要注意的关键一点是我没有选择任何服务为了解决此问题,我选择了“ iCloud文档”。

重建之前,您可能需要删除该应用程序。

本文地址:http://ios.askforanswer.com/xcode-6-ios-8-icloudhexinshujushezhi.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!