【问题标题】:Objective-C object into C Callback functionObjective-C 对象转换为 C 回调函数
【发布时间】:2014-06-18 15:54:37
【问题描述】:

目标:使用图案图像在 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 回调”

什么都没有,什么都没有。

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

【问题讨论】:

  • 您正试图从 C 函数访问您的类的实例变量 - 这是不可能的。只是一个建议 - 在调用 CGPatternCreate 之前使用全局变量并将其设置为指向您的视图控制器。这样您就可以在回调中访问该属性(例如 - controller.imageName.CGImage)。
  • 谢谢。我找到了。我用了一句话:-> static NSString *imageName = @"PatternImage1";

标签: objective-c c callback


【解决方案1】:

传递给回调的info 参数是您在调用CGPatternCreate() 时作为info 参数传递的任何值。在 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 通常是值得的。

【讨论】:

  • 非常感谢你们的cmets。我不知道在回调函数中调用Objective-C“-(void)”中的方法的语法,并且在搜索论坛中找不到它。我将使用您的建议来避免在每个函数调用中重复创建 NSObjects。因为当然我的项目做了更多的操作,比如改变图案的颜色。
  • 抱歉,我尝试了您提出的替代方案,但不起作用。现在我无法使用选定的图案图像进行绘制。
  • 我复制/粘贴了代码。但是我的应用程序可能有一些特殊性:也许这个事实会改变结果。我的应用程序是一个绘图应用程序(使用 Quartz2D),我使用的方法是:- (void) touchesMoved.
【解决方案2】:

找到了!!!

找到了 iiiiiiit !!!

static NSString *imageName = @"PatternImage1";

在回调函数中可见!!!

Yabba Dabba Doo !!!

完整的源代码。仅在“ViewController.m”中:

#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);

在代码的某些部分,“if/else”语句:

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);
}

【讨论】:

    猜你喜欢
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    相关资源
    最近更新 更多