Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.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 如何将客户端数据添加到SKNode/SKSpriteNode?_Ios_Model View Controller_Sprite Kit_Skspritenode_Sknode - Fatal编程技术网

Ios 如何将客户端数据添加到SKNode/SKSpriteNode?

Ios 如何将客户端数据添加到SKNode/SKSpriteNode?,ios,model-view-controller,sprite-kit,skspritenode,sknode,Ios,Model View Controller,Sprite Kit,Skspritenode,Sknode,我正在使用IOS SpriteKit,想知道是否有办法将客户端数据添加到sprite节点 例如,我希望将特定行为附加到节点、附加属性、与其他节点的关系等 我不愿意将SKNode作为子类,因为这样会破坏模型/视图/控制器模型,其中节点只是“视图” 目前,我保留了一个单独的控制器对象层次结构,但这感觉很笨拙,而且在性能方面也不是很好 什么是最佳实践?子类化在这方面不会改变任何东西。您仍然保留了完整的功能,并且什么也没有破坏。事实上,我认为如果你正在进行一场大型比赛,这几乎是不可避免的 但如果您确实不

我正在使用
IOS SpriteKit
,想知道是否有办法将客户端数据添加到sprite节点

例如,我希望将特定行为附加到节点、附加属性、与其他节点的关系等

我不愿意将
SKNode
作为子类,因为这样会破坏模型/视图/控制器模型,其中节点只是“视图”

目前,我保留了一个单独的控制器对象层次结构,但这感觉很笨拙,而且在性能方面也不是很好


什么是最佳实践?

子类化在这方面不会改变任何东西。您仍然保留了完整的功能,并且什么也没有破坏。事实上,我认为如果你正在进行一场大型比赛,这几乎是不可避免的

但如果您确实不想使用userData:

所有SKNode类都提供了一个可用于此目的的属性

您可以编写Objective-C类别,通过该类别可以添加其他属性,而无需子类化。下面是一个经过验证的模式

接口:

#import "YourCustomObject.h"

@interface SKNode (customObject)
@property (nonatomic) YourCustomObject* yourCustomObject;
@end
实施:

static NSString* YourCustomObjectUserDataKey = @"YourCustomObjectUserDataKey";

@implementation SKNode (customObject)
-(NSMutableDictionary*) internal_getOrCreateUserData
{
    NSMutableDictionary* userData = self.userData;
    if (userData == nil)
    {
        userData = [NSMutableDictionary dictionary];
        self.userData = userData;
    }

    return userData;
}

-(void) setYourCustomObject:(YourCustomObject*)customObject
{
    NSMutableDictionary* userData = [self internal_getOrCreateUserData];
    [userData setObject: customObject forKey:YourCustomObjectUserDataKey];
}

-(YourCustomObject*) yourCustomObject
{
    NSMutableDictionary* userData = [self internal_getOrCreateUserData];
    return (YourCustomObject*)[userData objectForKey:YourCustomObjectUserDataKey];
}
@end
YourCustomObject
替换为实际的类名

类别可以扩展为承载多个属性当然,您不必为每个属性编写单独的类别。该类别也不必位于SKNode上,如果您需要一个附加属性,但仅限于SKSpriteNode上,则可以将其设置为SKSpriteNode上的类别

通常,您需要访问
YourCustomObject
中的所属节点

因此,最好提供一个初始值设定项和/或属性,将所属节点作为输入。我更喜欢只读属性和自定义初始值设定项,因为通常您不希望在对象的整个生命周期中更改所有者。非常重要:此属性必须
,才能不创建保留周期

@interface YourCustomObject
@property (weak, readonly) SKNode* owningNode;
+(instancetype) customObjectWithOwningNode:(SKNode*)owningNode;
@end

@implementation YourCustomObject
+(instancetype) customObjectWithOwningNode:(SKNode*)owningNode
{
    return [[self alloc] initWithOwningNode:owningNode];
}
-(id) initWithOwningNode:(SKNode*)owningNode
{
    self = [super init];
    if (self) 
    {
        _owningNode = owningNode;
    }
    return self;
}
@end
然后,可以在节点类中创建和指定自定义对象:

YourCustomObject* customObject = [YourCustomObject customObjectWithOwningNode:self];
self.yourCustomObject = customObject;

虽然这里的其他答案已经提到您可以使用
userData
字典来处理任意键值,但我要补充的是,您可以对
SKNode
s进行子类化,因为SpriteKit一开始就不是MVC(或者至少在UIKit的意义上不是)


SKNode
s被设计为适合常见的游戏架构(组件模式和好友),实际上可以是模型、视图或控制器<代码>SKNode例如,它不是一个可显示的对象,但可以保存有关游戏实体/状态或其他子节点的信息。

我发现最好实现特定于其自身类中节点的行为。但是,如果您只想在节点中存储信息,控制器对象可以根据这些信息做出决策,那么可以使用userData属性。谢谢-这非常有用。我最终将其细分为一个快速解决方案。我在SKNode上读取时错过了用户数据!