gpt4 book ai didi

web-services - 用web服务同步IOS核心数据?

转载 作者:行者123 更新时间:2023-12-04 04:48:27 24 4
gpt4 key购买 nike

这是我的问题:

  • 我想使用核心数据 - 速度和连接问题来构建我的 IOS 应用程序。存储在核心数据中的数据来自 SQLServer 数据库,我可以通过尚未定义的 Web 服务访问该数据库。
  • 对存储在核心数据中的数据的任何更改都需要通过 Web 服务与 SQLServer 同步。此外,我需要缓冲由于连接问题而未同步的更改。
  • 我还需要使用服务器上发生的任何更改来更新核心数据。这可能会按照用户首选项中设置的时间表发生。

  • 我探索过的解决方案:
  • 使用 NSIncrementalStore类(IOS 5 中的新功能)。我对这到底做了什么感到非常困惑,但听起来很有希望。据我所知,你是 NSIncrementalStore 的子类它允许您拦截常规的核心数据 API 调用。然后,我可以将信息传递给核心数据,并通过 Web 服务将其与外部数据库同步。我可能完全错了。但假设我是对的,如果与互联网的连接中断,我将如何同步增量?
  • AFIncrementalStore - 这是 NSIncrementalStore 的子类使用 AFNetworking做网络服务部分。
  • RestKit - 我有点担心这个 API 的活跃程度,它似乎正在过渡到块功能。有没有人广泛使用这个?

  • 我倾向于 AFIncrementalStore因为这是使用(似乎是)更标准的方法。问题是,我可能完全不了解 NSIncrementalStore真的是。

    一些示例代码或教程的链接会很棒!

    最佳答案

    我对此的解决方案是将数据集的两个副本存储在 CoreData 数据库中。一个代表最后一个已知的服务器状态并且是不可变的。另一个由用户编辑。

    当需要同步更改时,应用程序会在数据的编辑副本和不可变副本之间创建差异。应用程序将差异发送到 Web 服务,该服务将差异应用于其自己的数据副本。它回复数据集的完整副本,应用程序将其覆盖到它的两个数据副本上。

    优点是:

  • 如果没有网络连接,则不会丢失任何更改:每次需要发送数据集时都会计算差异,并且不可变副本仅在成功同步时更改。
  • 仅传输需要发送的最少量信息。
  • 多人可以同时编辑相同的数据,而无需使用锁定策略,通过覆盖将数据丢失的机会降至最低。

  • 缺点是:
  • 编写不同的代码很复杂。
  • 编写合并服务很复杂。
  • 除非您是元编程大师,否则您会发现您的差异/合并代码很脆弱,并且必须在您更改对象模型时进行更改。

  • 以下是我在提出策略时的一些考虑:
  • 如果您允许离线进行更改, checkin / checkout 锁定将不起作用(如何在没有连接的情况下建立锁定?)。
  • 如果两个人同时编辑相同的数据会怎样?
  • 如果一个人在没有连接的情况下在一台 iOS 设备上编辑数据,将其关闭,在另一台设备上编辑,然后重新打开原始设备,会发生什么情况?
  • CoreData 多线程本身就是一个完整的问题类。

  • 我听说过的最接近开箱即用的支持来做任何这样的远程操作是 iOS6 中新的 iCloud/CoreData 同步系统,当实体发生变化时,它会自动将实体从 CoreData 数据库传输到 iCloud。但是,这意味着您必须使用 iCloud。

    编辑:这已经很晚了,我知道,但这里有一个能够在两个 NSManagedObject 实例之间产生差异的类。
    // SZManagedObjectDiff.h
    @interface SZManagedObjectDiff

    - (NSDictionary *)diffNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject

    @end

    // SZManagedObjectDiff.m
    #import "SZManagedObjectDiff.h"

    @implementation SZManagedObjectDiff

    - (NSDictionary *)diffNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject {

    NSDictionary *attributeDiff = [self diffAttributesOfNewObject:newObject withOldObject:oldObject];

    NSDictionary *relationshipsDiff = [self diffRelationshipsOfNewObject:newObject withOldObject:oldObject];

    NSMutableDictionary *diff = [NSMutableDictionary dictionary];

    if (attributeDiff.count > 0) {
    diff[@"attributes"] = attributeDiff;
    }

    if (relationshipsDiff.count > 0) {
    diff[@"relationships"] = relationshipsDiff;
    }

    if (diff.count > 0) {
    diff[@"entityName"] = newObject ? newObject.entity.name : oldObject.entity.name;

    NSString *idAttributeName = newObject ? newObject.entity.userInfo[@"id"] : oldObject.entity.userInfo[@"id"];

    if (idAttributeName) {
    id itemId = newObject ? [newObject valueForKey:idAttributeName] : [oldObject valueForKey:idAttributeName];

    if (itemId) {
    diff[idAttributeName] = itemId;
    }
    }
    }

    return diff;
    }

    - (NSDictionary *)diffRelationshipsOfNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject {

    NSMutableDictionary *diff = [NSMutableDictionary dictionary];

    NSDictionary *relationships = newObject == nil ? [[oldObject entity] relationshipsByName] : [[newObject entity] relationshipsByName];

    for (NSString *name in relationships) {

    NSRelationshipDescription *relationship = relationships[name];

    if (relationship.deleteRule != NSCascadeDeleteRule) continue;

    SEL selector = NSSelectorFromString(name);

    id newValue = nil;
    id oldValue = nil;

    if (newObject != nil && [newObject respondsToSelector:selector]) newValue = [newObject performSelector:selector];
    if (oldObject != nil && [oldObject respondsToSelector:selector]) oldValue = [oldObject performSelector:selector];

    if (relationship.isToMany) {

    NSArray *changes = [self diffNewSet:newValue withOldSet:oldValue];

    if (changes.count > 0) {
    diff[name] = changes;
    }

    } else {

    NSDictionary *relationshipDiff = [self diffNewObject:newValue withOldObject:oldValue];

    if (relationshipDiff.count > 0) {
    diff[name] = relationshipDiff;
    }
    }
    }

    return diff;
    }

    - (NSDictionary *)diffAttributesOfNewObject:(NSManagedObject *)newObject withOldObject:(NSManagedObject *)oldObject {

    NSMutableDictionary *diff = [NSMutableDictionary dictionary];

    NSArray *attributeNames = newObject == nil ? [[[oldObject entity] attributesByName] allKeys] : [[[newObject entity] attributesByName] allKeys];

    for (NSString *name in attributeNames) {

    SEL selector = NSSelectorFromString(name);

    id newValue = nil;
    id oldValue = nil;

    if (newObject != nil && [newObject respondsToSelector:selector]) newValue = [newObject performSelector:selector];
    if (oldObject != nil && [oldObject respondsToSelector:selector]) oldValue = [oldObject performSelector:selector];

    newValue = newValue ? newValue : [NSNull null];
    oldValue = oldValue ? oldValue : [NSNull null];

    if (![newValue isEqual:oldValue]) {
    diff[name] = @{ @"new": newValue, @"old": oldValue };
    }
    }

    return diff;
    }

    - (NSArray *)diffNewSet:(NSSet *)newSet withOldSet:(NSSet *)oldSet {

    NSMutableArray *changes = [NSMutableArray array];

    // Find all items that have been newly created or updated.
    for (NSManagedObject *newItem in newSet) {

    NSString *idAttributeName = newItem.entity.userInfo[@"id"];

    NSAssert(idAttributeName, @"Entities must have an id property set in their user info.");

    id newItemId = [newItem valueForKey:idAttributeName];

    NSManagedObject *oldItem = nil;

    for (NSManagedObject *setItem in oldSet) {
    id setItemId = [setItem valueForKey:idAttributeName];

    if ([setItemId isEqual:newItemId]) {
    oldItem = setItem;
    break;
    }
    }

    NSDictionary *diff = [self diffNewObject:newItem withOldObject:oldItem];

    if (diff.count > 0) {
    [changes addObject:diff];
    }
    }

    // Find all items that have been deleted.
    for (NSManagedObject *oldItem in oldSet) {

    NSString *idAttributeName = oldItem.entity.userInfo[@"id"];

    NSAssert(idAttributeName, @"Entities must have an id property set in their user info.");

    id oldItemId = [oldItem valueForKey:idAttributeName];

    NSManagedObject *newItem = nil;

    for (NSManagedObject *setItem in newSet) {
    id setItemId = [setItem valueForKey:idAttributeName];

    if ([setItemId isEqual:oldItemId]) {
    newItem = setItem;
    break;
    }
    }

    if (!newItem) {
    NSDictionary *diff = [self diffNewObject:newItem withOldObject:oldItem];

    if (diff.count > 0) {
    [changes addObject:diff];
    }
    }
    }

    return changes;
    }

    @end

    这里有更多关于它做什么、它是如何做的以及它的限制/假设的信息:

    http://simianzombie.com/?p=2379

    关于web-services - 用web服务同步IOS核心数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11961304/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com