Why is -removeFromParent in SKNode throwing this exception?

102 views Asked by At

The exception is:

-[__NSArrayI removeExactObject:]: unrecognized selector sent to instance

I want to have a representation of a SKScene in a NSTreeController, for that I’m using a Proxy class that holds a strong reference to a SKNode and to its proxy children, with each instance of the Proxy class in turn being used as the represented object in the tree controller.

NSTreeController
|-Proxy             ->   SKScene
    |-Proxy         ->      |-SKSpriteNode
    |-Proxy         ->      |-SKNode
        |-Proxy     ->          |-SKSpriteNode
        |-Proxy     ->          |-SKShapeNode

All nodes are added or removed to the scene via these methods in the Proxy class

@interface Proxy : NSObject
+ (instancetype)proxyWithNode:(id)node;
@end

@implementation Proxy {
    SKNode *_node;
    NSMutableArray *_proxyChildren;
}

+ (instancetype)proxyWithNode:(id)node {
    if (node) {
        Proxy *proxy = [[Proxy alloc] init];
        proxy.node = node;
        return proxy;
    }
    return nil;
}

- (void)setNode:(id)node {
    _proxyChildren = [NSMutableArray array];

    for (id child in [node children]) {
        Proxy *childProxy = [Proxy proxyWithNode:child];
        [_proxyChildren addObject:childProxy];
    }

    _node = node;
}

- (id)node {
    return _node;
}

- (void)setChildren:(NSMutableArray *)children {

    //[_node removeAllChildren];
    [self cleanUpChildren:_node];

    for (Proxy *child in children) {
        [_node addChild:child.node];
    }

    _proxyChildren = children;
}

- (NSMutableArray *)children {
    return _proxyChildren;
}

- (void)cleanUpChildren:(SKNode *)node {
    for (SKNode *child in node.children) {
        [self cleanUpChildren:child];
        //assert(child.parent == node);
        @try {
            //NSLog(@"\n%p %p\n%@\n%@\n\n", node, child, node, child);
            [child removeFromParent];
        }
        @catch (NSException *exception) {
            NSLog(@"WTF!");
        }

    }
}
@end

This is how to I populate the tree controller with the scene

[_treeController setContent:[Proxy proxyWithNode:scene]];

The problem is that at some point when the tree controller tries to remove a proxy node from its parent the SKNode throws the exception above

This is how I'm removing a proxy node

[_treeController removeObjectAtArrangedObjectIndexPath:indexPath];
1

There are 1 answers

0
rraallvv On

This is the quick and dirty fix I came up with:

- (void)setChildren:(NSMutableArray *)children {

    id privateChildren = [_node valueForKey:@"_children"];
    if (![privateChildren isKindOfClass:[NSMutableArray class]]) {
        [_node setValue:[privateChildren mutableCopy] forKey:@"_children"];
    }

    [_node removeAllChildren];
    //[self cleanUpChildren:_node];

    //...
}

I check whether the private ivar _children is an inmutable array, if so I make it a mutable copy before trying to remove the children.