Objective-C对象转换为C回调函数

时间:2014-06-18 15:54:37

标签: objective-c c callback

目标:使用模式图像在Quartz 2D中绘制。目前:

const CGPatternCallbacks kPatternCallbacks = {0, routine, NULL};

void routine(void *info, CGContextRef contextRef) {

    UIImage *brushTexture = [UIImage imageNamed:@"PatternImage1"];

    CGContextDrawImage(contextRef, CGRectMake(0, 0, 50, 50), brushTexture.CGImage);
}

用于:

    CGPatternRef strokePattern = CGPatternCreate(NULL,
                                                 CGRectMake(0, 0, 50, 50),
                                                 CGAffineTransformIdentity,
                                                 50, // horizontal spacing
                                                 50, // vertical spacing
                                                 kCGPatternTilingNoDistortion,
                                                 true,
                                                 &kPatternCallbacks);

所有这些东西都在实现类(ViewController.m)中。而且完美,我可以绘制图案图像。

问题:动态改变C回调函数中的内容,例如:

在“ViewController.h”中

@interface ViewController : UIViewController {
    NSString *imageName;
}

@property (nonatomic, strong) NSString *imageName;

在实现类(ViewController.m)

@synthesize imageName;

imageName = @"PatternImage1";

void routine(void *info, CGContextRef contextRef) {

    //UIImage *brushTexture = [UIImage imageNamed:@"PatternImage1"];

    //CGContextDrawImage(contextRef, CGRectMake(0, 0, 50, 50), brushTexture.CGImage);
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 50, 50), imageName.CGImage);
}

错误! - >使用未声明的标识符'imageName'

我已经尝试过了......

void routine(void *info, CGContextRef contextRef) {

    //NSString *imageName = CFBridgingRelease(info);     //<- not working

    //NSString *imageName = (__bridge NSString *)(info);  //<- not working

    NSString *imageName = (__bridge NSString *) info;     //<- not working


    //UIImage *brushTexture = [UIImage imageNamed:@"PatternImage1"];

    CGContextDrawImage(contextRef, CGRectMake(0, 0, 50, 50), imageName.CGImage);
}

例程结构不能更改,因为它是由CGPatternCallbacks定义的。

void routine(void *info, CGContextRef contextRef) { }

我搜索了很多但没有找到解决方案。主题如:

  • “将Objective-C对象传递给C函数”

  • “混合Objective-C和C”

  • “回调功能”

  • “C Callbacks”

没什么,什么也没有。

不可能?我不这么认为!我将不得不放弃...... F ***!

2 个答案:

答案 0 :(得分:2)

传递给回调的info参数是您在调用info时作为CGPatternCreate()参数传递的任何值。在Objective-C代码中,您通常会传递(__bridge void*)self。然后,在你的回调中,你将它转换回适当的类型并调用方法来完成实际的工作:

void routine(void *info, CGContextRef contextRef) {
    ViewController* self = (__bridge ViewController*)info;
    [self drawPattern:contextRef];
}

- (void) drawPattern:(CGContextRef)contextRef {
    UIImage *brushTexture = [UIImage imageNamed:imageName]; // <- imageName can be an ivar
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 50, 50), brushTexture.CGImage);
}

在您只想传递图像名称字符串的非常简单的情况下,您可以将NSString*作为info指针传递。甚至是从名称创建的UIImage*,因此您不必每次都创建它。这避免了在恢复的self上调用方法的需要。但是,即使您现在的需求很简单,也有更复杂的需求是很常见的,因此传递self通常是值得的。

答案 1 :(得分:0)

找到它!!!

发现iiiiiiiit !!!

static NSString *imageName = @"PatternImage1";

在回调函数中可见!!!!

Yabba Dabba Doo !!!

完整的源代码。只在&#34; ViewController.m&#34; :

#import "ViewController.h"

@implementation ViewController

static NSString *imageName = @"PatternImage1";

在代码的某些部分:

const CGPatternCallbacks kPatternCallbacks = {0, routine, NULL};

在代码的某些部分:

CGPatternRef strokePattern = CGPatternCreate(NULL, CGRectMake(0,0,50,50),
                                                 CGAffineTransformIdentity,
                                                 50, 50,
                                                 kCGPatternTilingNoDistortion,
                                                 true,
                                                 &kPatternCallbacks);

在代码的某些部分,&#34; if / else&#34;语句:

if () {
  imageName = @"PatternImage2";

} else if () {
  imageName = @"PatternImage3";

} else {
  imageName = @"PatternImage4";
}

最后,回调函数:

void routine(void *info, CGContextRef contextRef) {

    UIImage *brushTexture = [UIImage imageNamed:imageName];

    CGContextDrawImage(contextRef, CGRectMake(0, 0, 50, 50), brushTexture.CGImage);
}