开发者

Observed Object not Registered as an Observer

开发者 https://www.devze.com 2023-02-25 15:07 出处:网络
I am having an issue when my array controller is refreshed with new data retrieved from a server request.

I am having an issue when my array controller is refreshed with new data retrieved from a server request.

The Setup

I have an entity object (call it MyParent) which has a few properties:

name
age
description
widgetID

And an entity object (call it MyWidget) which has a few properties:

name
size
description

The size is a string representation of an NSSize object. It makes for easy storage and retrieval from the core data store and to the server and back in JSON. In order to represent the size in the UI, I have subclassed the MyWidget and provided a custom setter and getter as a category of the custom class (I did this so Xcode doesn't overwrite my changes if I need to make changes to the model):

-(void)setObjectWidth:(NSInteger)aValue {
    [self setObjectSize:NSMakeSize(aValue, [self objectHeight])];
}

-(void)setObjectHeight:(NSInteger)aValue {
    [self setObjectSize:NSMakeSize([self objectWidth], aValue)];
}

-(void)setObjectSize:(NSSize开发者_运维问答)aValue {
    [self setSize:NSStringFromSize(aValue)];
}

-(NSInteger)objectWidth {
    return [self objectSize].width;
}

-(NSInteger)objectHeight {
    return [self objectSize].height;
}

-(NSSize)objectSize {
    return NSSizeFromString([self size]);
}

I get the widget by doing a lookup on the widgetId as a category method on the parent:

-(MyWidget *)widget {
    NSManagedObjectContext * moc = [[NSApp delegate] managedObjectContext];

    return [moc fetchObjectForEntityName:@"MyWidget"
                                 withUID:[self widgetID]];
}

The fetchObjectForEntityName:withUID is a category on the managed object context.

Within the UI I have an array controller bound to a tableView of MyParent objects. Selecting an object presents the details in the UI which are bound to the appropriate values:

parentArrayController --> parentArray (managed objects in an array)
parentTable --> parentArrayController.arrangedObjects.name

uiWidthTextField --> parentArrayController.selection.widget.objectWidth
uiHeightTextField --> parentArrayController.selection.widget.objectHeight

The array controller is observed for changes so that it can fire off a notification for other parts of the app that need to know the selected object changed

What Works

Everything works well. I can make changes to the text fields within the UI and it sets and gets the size from the widget as you would expect. Adding a parent item is a simple task of creating a NSURLConnection and sending the appropriate params off to the server. When the server acknowledges the add, I request the list of parent items form the server again.

The list that comes down is compared to the existing list in core data and adds the new item and makes any other changes to other object values that are already there.

What's Broken

When the list comes back, it is parsed correctly, but the app complains when the array controller is being updated:

Serious application error. Exception was caught during Core Data change processing: Cannot remove an observer for the key path "widget.objectHeight" from because it is not registered as an observer. with userInfo (null)

Cannot remove an observer for the key path "widget.objectHeight" from because it is not registered as an observer.

What I've Tried

I have tried to add a willChangeValueForKey: and didChangeValueForKey: wrapped around the setter of the objectHeight and objectWidth, but this seems to provide no recourse.

I believe the issue is because IB is bound to the widget.objectHeight and widget is a lookup on the parent as opposed to a true KVO/KVC property. However, I don't need a setter on widget (although I'll be trying that next).

I know I'm missing something, but can't place my finger on it.

The Plea

Any help or assistance with resolving this would be very much appreciated!


You need to set objectWidth and objectHeight as non-modeled properties of MyWidget. You are having KVO problems because objectWidth and objectHeightare not keys of MyWidget but just have method names in the form of getters and setters.

Just add:

@property() NSInteger objectWidth;
@property() NSInteger objectHeight;

to the MyWidget class and that should provide the keys for KVO to work. (Might want to double check my property form. It's been a while sense I had to write an integer property.)

0

精彩评论

暂无评论...
验证码 换一张
取 消