Ios 使用Sprite工具包创建自定义滑块-如何传递@selector?

Ios 使用Sprite工具包创建自定义滑块-如何传递@selector?,ios,objective-c,selector,sprite-kit,Ios,Objective C,Selector,Sprite Kit,我正在开发的一款精灵套件游戏使用自定义滑块作为颜色选择器(颜色从滑块轨迹图形中拾取,该图形是包含渐变的UIImage) 我考虑过使用定制的UISlider,但是标准的IOS UI控件不能很好地与Sprite Kit的场景配合使用:它们很难相对于场景的其余部分进行定位(因为它们是作为主视图的子视图而不是作为SKScene的一部分存在),它们会突然出现(而不是与场景的其余部分过渡)并且在退出场景时必须手动删除。简言之,实现它们是一件痛苦的事情,而且它们无法无缝集成 我已经开始使用SKSpriteNo

我正在开发的一款精灵套件游戏使用自定义滑块作为颜色选择器(颜色从滑块轨迹图形中拾取,该图形是包含渐变的
UIImage

我考虑过使用定制的
UISlider
,但是标准的IOS UI控件不能很好地与Sprite Kit的场景配合使用:它们很难相对于场景的其余部分进行定位(因为它们是作为主视图的子视图而不是作为
SKScene
的一部分存在),它们会突然出现(而不是与场景的其余部分过渡)并且在退出场景时必须手动删除。简言之,实现它们是一件痛苦的事情,而且它们无法无缝集成

我已经开始使用
SKSpriteNode
s实现自定义滑块,在的基础上构建,并将滑块轨迹和手柄放置到位。手柄沿轨迹左右滑动,并将值设置在0和1之间(就像
UISlider
)。我调用了此类
SKSlider

我想做的是传递
SKSlider
一个
@选择器
,方式与传递
UISlider
的方式大致相同,因此我可以在
SKScene
中定义一个函数,以便滑块执行:

[mySlider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
滑块更改时我尝试调用的函数如下所示:

-(UIColor*)getRGBAFromImage:(UIImage*)image atX:(float)xp atY:(float)yp
{
    NSMutableArray *resultColor = [NSMutableArray array];   
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));

    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;

    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGColorSpaceRelease(colorSpace);



    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

    CGContextRelease(context);

    // Now your rawData contains the image data in the RGBA8888 pixel format.

    int byteIndex = (bytesPerRow * yp) + xp * bytesPerPixel;
    CGFloat red   = (rawData[byteIndex]     * 1.0) /255.0;
    CGFloat green = (rawData[byteIndex + 1] * 1.0)/255.0 ;
    CGFloat blue  = (rawData[byteIndex + 2] * 1.0)/255.0 ;
    CGFloat alpha = (rawData[byteIndex + 3] * 1.0) /255.0;

    byteIndex += 4;

    UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];

    [resultColor addObject:color];

    NSLog(@"width:%i hight:%i Color:%@",width,height,[color description]);

    free(rawData);

    return color;        
}
(为感兴趣的人找到了代码。)


但是我不确定应该如何在
SKSlider
的界面中设置此选项。有人能为我指出正确的方向吗?

只需在自定义滑块中实现缺少的方法。在界面中添加此选项:

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
在实现中,将
目标
操作
存储为属性

@property (nonatomic, strong) id target;
@property (nonatomic) SEL action;

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
{
    _target = target;
    _action = action;
}
然后在值更改时对
目标调用
操作

objc_msgSend(_target, _action);
请记住导入:

#import <objc/message.h>

选择器的变量类型是
SEL
。以下是如何声明属性以跟踪目标和操作。(请注意,
SEL
是指向结构的指针,而不是指向对象的指针,因此指定
strong
将使编译器不安。)

下面是一个更新目标和操作的示例方法

- (void)changeTarget:(id)target action:(SEL)action
{
    self.target = target;
    self.action = action;
}
这就是对目标调用action方法的方式

[self.target performSelector:self.action withObject:self afterDelay:0.0];
请注意,self是作为参数传递给方法的,因此目标中的方法签名应该是

- (void)someAction:(id)sender

嗯,我想是这样的……但是现在出现了错误:
ARC不允许将Objective-C指针隐式转换为'SEL'(也称为'SEL*),而
PerformSelector可能会导致泄漏,因为它的选择器未知。
…我仍然收到ARC限制警告,说不允许隐式转换:(我想差不多了!据我所知,我称之为:
[skinSlider addTarget:self action:@selector(getRGBAFromImage:atX:atY:)withObject:skinGradient withObject:skinSlider.value withObject:0 forControlEvents:UIControlEventValueChanged];
(传入变量),那么我应该如何更改界面?不要将不应该在滑块中的逻辑放入其中。滑块是一个控件。它应该只进行滑动并将其告知目标。然后,目标对象(可能是您的视图控制器或场景)我更新了我的答案。太棒了。这非常有效,你告诉了我一些新的事情。一千个感谢、投票、接受等等。reecon打败了你(只是),但你的答案也很有用:投票。
[self.target performSelector:self.action withObject:self afterDelay:0.0];
- (void)someAction:(id)sender