jjzjj

objective-c - NSFetchRequest 的 NSSortDescriptor 在上下文保存后不起作用

coder 2023-09-26 原文

我在 GCD 调度队列中对 NSManagedObjectContext 进行操作,定义如下:

- (NSManagedObjectContext *)backgroundContext
{
    if (backgroundContext == nil) {
        self.backgroundContext = [NSManagedObjectContext MR_contextThatNotifiesDefaultContextOnMainThread];
    }
    return backgroundContext;
}

MR_contextThatNotifiesDefaultContextOnMainThread 是来自 MagicalRecord 的方法:

NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:[NSManagedObjectContext MR_defaultContext]];
return context;

在获取我的对象并为它们提供正确的队列位置后,我记录了它们并且顺序是正确的。然而,第二个日志似乎是完全随机的,排序描述符显然不起作用。

我已将问题缩小到 [self.backgroundContext save:&error]。保存后台上下文后,排序描述符被破坏。

dispatch_group_async(backgroundGroup, backgroundQueue, ^{
    // ...

    for (FooObject *obj in fetchedObjects) {
        // ...
        obj.queuePosition = [NSNumber numberWithInteger:newQueuePosition++];
    }

    NSFetchRequest *f = [NSFetchRequest fetchRequestWithEntityName:[FooObject entityName]];
    f.predicate = [NSPredicate predicateWithFormat:@"queuePosition > 0"];
    f.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"queuePosition" ascending:YES]];
    NSArray *queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil];
    for (FooObject *obj in queuedObjects) {
        DLog(@"%@ %@", obj.queuePosition, obj.title);
    }

    if ([self.backgroundContext hasChanges]) {
        DLog(@"Changes");
        NSError *error = nil;
        if ([self.backgroundContext save:&error] == NO) {
            DLog(@"Error: %@", error);
        }
    }

    queuedObjects = [self.backgroundContext executeFetchRequest:f error:nil];
    for (FooObject *obj in queuedObjects) {
        DLog(@"%@ %@", obj.queuePosition, obj.title);
    }

});

我不知道为什么排序描述符不起作用,任何 Core Data 专家都想帮忙吗?

更新:

在iOS 4上没有出现这个问题。我认为原因在于线程隔离和私有(private)队列模式之间的差异。 MagicalRecord 自动使用新的并发模式,它的行为似乎有所不同。

更新 2:

问题已通过添加后台上下文的保存解决:

if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) {
    DLog(@"Changes");
    NSError *error = nil;
    if ([[NSManagedObjectContext MR_contextForCurrentThread] save:&error] == NO) {
        DLog(@"Error: %@", error);
    } else {
        NSManagedObjectContext *parent = [NSManagedObjectContext MR_contextForCurrentThread].parentContext;
        [parent performBlockAndWait:^{
            NSError *error = nil;
            if ([parent save:&error] == NO) {
                DLog(@"Error saving parent context: %@", error);
            }
        }];
    }
}

更新 3:

MagicalRecord 提供了一种递归保存上下文的方法,现在我的代码如下所示:

if ([[NSManagedObjectContext MR_contextForCurrentThread] hasChanges]) {
    DLog(@"Changes");
    [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveWithErrorHandler:^(NSError *error) {
        DLog(@"Error saving context: %@", error);
    }];
}

一开始没有使用它让我感到羞耻......

但是,我不知道为什么这有帮助,很想得到解释。

最佳答案

我会尝试发表评论,因为我写了 MagicalRecord。

因此,在iOS5上,MagicalRecord被设置为尝试使用多个托管对象上下文的新的Private Queue方法。这意味着子上下文中的保存只会将保存推送到父上下文。只有当没有更多 parent 的 parent 保存时,保存才会保存到其商店。这可能就是您的 MagicalRecord 版本中发生的情况。

MagicalRecord 已尝试在以后的版本中为您处理此问题。也就是说,它会尝试在私有(private)队列模式和线程隔离模式之间进行选择。正如您所发现的,这并不太奏效。为 iOS4 和 iOS5 编写代码(没有复杂的预处理器规则等)的唯一真正兼容的方法是使用经典的线程隔离模式。 1.8.3 标签中的 MagicalRecord 支持这一点,并且应该适用于两者。从 2.0 开始,它将只是私有(private)队列。

而且,如果您查看 MR_save 方法,您会发现它也在为您执行 hasChanges 检查(这也可能是不需要的,因为 Core Data 内部也可以处理)。无论如何,您应该编写和维护的代码更少...

关于objective-c - NSFetchRequest 的 NSSortDescriptor 在上下文保存后不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10120938/

有关objective-c - NSFetchRequest 的 NSSortDescriptor 在上下文保存后不起作用的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  3. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  4. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  5. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  6. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  7. ruby - 在 Ruby 中,在类方法的上下文中,什么是实例变量和类变量? - 2

    如果我有以下一段Ruby代码:classBlahdefself.bleh@blih="Hello"@@bloh="World"endend@blih和@@bloh到底是什么?@blih是Blah类中的一个实例变量,@@bloh是Blah类中的一个类变量,对吗?这是否意味着@@bloh是Blah的类Class中的一个变量? 最佳答案 人们似乎忽略了该方法是类方法。@blih将是常量Bleh的类Class实例的实例变量。因此:irb(main):001:0>classBlehirb(main):002:1>defself.blehirb

  8. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  9. ruby-on-rails - Rails 3.2 防止使用错误保存对象 - 2

    我有一个ActiveRecord对象,我想在不对模型进行永久验证的情况下阻止它被保存。您过去可以使用errors.add执行类似的操作,但它看起来不再有效了。user=User.lastuser.errors.add:name,"namedoesn'trhymewithorange"user.valid?#=>trueuser.save#=>true或user=User.lastuser.errors.add:base,"myuniqueerror"user.valid?#=>trueuser.save#=>true如何在不修改用户对象模型的情况下防止将用户对象保存在Rails3.2中

  10. ruby - 你会如何在 Ruby 中表达成语 "with this object, if it exists, do this"? - 2

    在Ruby(尤其是Rails)中,您经常需要检查某物是否存在,然后对其执行操作,例如:if@objects.any?puts"Wehavetheseobjects:"@objects.each{|o|puts"hello:#{o}"end这是最短的,一切都很好,但是如果你有@objects.some_association.something.hit_database.process而不是@objects呢?我将不得不在if表达式中重复两次,如果我不知道实现细节并且方法调用很昂贵怎么办?显而易见的选择是创建一个变量,然后测试它,然后处理它,但是你必须想出一个变量名(呃),它也会在内存中

随机推荐