Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios KVO核心数据和基本访问器_Ios_Cocoa_Core Data_Key Value Observing_Primitive - Fatal编程技术网

Ios KVO核心数据和基本访问器

Ios KVO核心数据和基本访问器,ios,cocoa,core-data,key-value-observing,primitive,Ios,Cocoa,Core Data,Key Value Observing,Primitive,我对iPhone应用程序上的核心数据属性的自定义访问器方法有问题。我想做的不仅仅是拉出原语类型并返回它。我有一个可能的activityType的NSSet,如果对象没有primitiveType,那么我希望在该集合中查找并返回与我的类上的另一个变量匹配的activityType 下面是我为实现这一点而编写的代码。代码的问题是,我对[self-willChangeValueForKey:@“type”]的调用导致了一个无限循环,其中程序不断抛出NSLog“将type设置为…”-可能是因为我在访问器

我对iPhone应用程序上的核心数据属性的自定义访问器方法有问题。我想做的不仅仅是拉出原语类型并返回它。我有一个可能的activityType的NSSet,如果对象没有primitiveType,那么我希望在该集合中查找并返回与我的类上的另一个变量匹配的activityType

下面是我为实现这一点而编写的代码。代码的问题是,我对
[self-willChangeValueForKey:@“type”]
的调用导致了一个无限循环,其中程序不断抛出NSLog“将type设置为…”-可能是因为我在访问器中调用了willChange

如果我取出
[self-willChangeValueForKey:@“type”]
我不会得到循环,程序运行正常,下次我尝试访问对象上的类型时,基本类型被正确调用。但是,当我告诉ManagedObjectContext是时候保存了时,它告诉我任何对象都没有更改-因此,由于我没有调用willChangeValueForKey-对原语类型的更改永远不会为对象保留

- (ActivityType *)type {

[self willAccessValueForKey:@"type"];
ActivityType *myType = [self primitiveType];
[self didAccessValueForKey:@"type"];

if (myType != nil) {
    NSLog(@"Use primitive (%@)", [myType myDescription]);

} else {

    // 1) find type
    NSSet *types = self.myActivityTypes;

    NSSet *foundTypes = [types objectsPassingTest:^BOOL(id obj, BOOL *stop) {
        ActivityType *object = (ActivityType *) obj;

        return ([object.typeName isEqualToString:self.activityTypeName]);

    }];

    myType = [foundTypes allObjects][0];

    NSLog(@"Setting type to %@", [myType myDescription]);

    // in this case we should not alert anyone since we are inside the getter?
    [self willChangeValueForKey:@"type"];
    [self setPrimitiveType:myType];
    [self didChangeValueForKey:@"type"];


}

return myType;

}

托管对象属性观察机制将使用访问器检查新旧值。由于您正在更改getter中的值,因此将再次调用getter,因此您的无限循环开始

这种延迟加载实际上不适用于托管对象。您可以在其他位置设置活动类型,例如awakeFromFetch,或者在设置activityTypeName时设置,或者如果不合适,则实现单独的访问器:

-(ActivityType*)calculatedActivityType
{
    ActivityType *myType = self.activityType;
    if (myType) return myType;

    NSSet *types = self.myActivityTypes;

    NSSet *foundTypes = [types objectsPassingTest:^BOOL(id obj, BOOL *stop) {
        ActivityType *object = (ActivityType *) obj;

        return ([object.typeName isEqualToString:self.activityTypeName]);

    }];

    myType = [foundTypes allObjects][0];
    self.activityType = myType;
    return myType;
}

这不会导致任何循环,因为您不在任何访问器中

托管对象属性观察机制将使用访问器检查新旧值。由于您正在更改getter中的值,因此将再次调用getter,因此您的无限循环开始

这种延迟加载实际上不适用于托管对象。您可以在其他位置设置活动类型,例如awakeFromFetch,或者在设置activityTypeName时设置,或者如果不合适,则实现单独的访问器:

-(ActivityType*)calculatedActivityType
{
    ActivityType *myType = self.activityType;
    if (myType) return myType;

    NSSet *types = self.myActivityTypes;

    NSSet *foundTypes = [types objectsPassingTest:^BOOL(id obj, BOOL *stop) {
        ActivityType *object = (ActivityType *) obj;

        return ([object.typeName isEqualToString:self.activityTypeName]);

    }];

    myType = [foundTypes allObjects][0];
    self.activityType = myType;
    return myType;
}

这不会导致任何循环,因为您不在任何访问器中

另一个解决方案可能是由访问器返回新类型,而不更改基础值类型。而且。。。在当前队列上异步调度更改

dispatch_async(dispatch_get_current_queue(), ^{
    [self willChangeValueForKey:@"type"];
    [self setPrimitiveType:myType];
    [self didChangeValueForKey:@"type"];
});

这并不完美,我可以想象这可能会导致“查找代码”执行多次。

另一种解决方案可能是由访问器返回新类型,而不更改基础值类型。而且。。。在当前队列上异步调度更改

dispatch_async(dispatch_get_current_queue(), ^{
    [self willChangeValueForKey:@"type"];
    [self setPrimitiveType:myType];
    [self didChangeValueForKey:@"type"];
});

这并不完美,我可以想象这可能会导致“查找代码”执行多次。

为什么不使用set访问器,例如self.type=myType?您正在通过在访问器中执行的操作绕过访问器;将程序放入与发出willChangeValueForKey警告相同的无限循环中。我有一个答案给你,我会把它润色一下,稍后再发。你为什么不直接使用set访问器,例如self.type=myType?您正在通过在访问器中执行的操作绕过访问器;将程序放入与发出willChangeValueForKey警告相同的无限循环中。我有一个答案给你,我会把它润色一下,稍后再发。非常感谢你——这是一个很好的解决方案!作为记录,如果将来有人尝试这样做-使用awakeFromFetch似乎是一个很好的解决方案,并且在实施和测试时,数据似乎保存到了数据库中-至少对象看起来脏了,并且
managedObjectContext.hasChanges
是真的。但是,当程序退出并重新运行时对象仍然是动态创建的,所以在awakeFromFetch中设置对象的部分似乎不是一个好主意。此时对象可能处于不一致的状态。但是
calculatedActivityType
的建议就像一个魔咒,非常感谢你——这是一个很好的解决方案!作为记录,如果将来有人尝试这样做-使用awakeFromFetch似乎是一个很好的解决方案,并且在实施和测试时,数据似乎保存到了数据库中-至少对象看起来脏了,并且
managedObjectContext.hasChanges
是真的。但是,当程序退出并重新运行时对象仍然是动态创建的,所以在awakeFromFetch中设置对象的部分似乎不是一个好主意。此时对象可能处于不一致的状态。但是
calculatedActivityType
的建议非常有效