为什么SKNode中的-removeFromParent会抛出此异常?

时间:2015-06-08 11:14:45

标签: sprite-kit nstreecontroller

例外是:

  

- [__ NSArrayI removeExactObject:]:无法识别的选择器发送到实例

我希望在SKScene中代表NSTreeController,因为我使用的是Proxy类,其中包含对SKNode的强引用到它的代理子节点,Proxy类的每个实例又被用作树控制器中的表示对象。

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

通过Proxy类

中的这些方法将所有节点添加或移除到场景中
@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

这是我如何使用场景填充树控制器

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

问题在于,当树控制器尝试从其父节点中删除代理节点时,SKNode会抛出上面的异常

这就是我删除代理节点的方式

[_treeController removeObjectAtArrangedObjectIndexPath:indexPath];

1 个答案:

答案 0 :(得分:0)

这是我想出的快速而肮脏的修复:

- (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];

    //...
}

我检查私有ivar _children是否是一个不可改变的数组,如果是这样的话,我会在尝试删除子代之前将其作为一个可变副本。