typedef结构中的Objective-c对象(在ARC中禁止)

时间:2012-12-03 22:41:01

标签: xcode object struct automatic-ref-counting

我是Objective-C编程和Xcode的新手。我继承了一个项目的旧版本(3.2.5),最近我把它转换为最新版本(4.5.2)。我将这个项目转换为ARC,我遇到了在typedef结构中找到的objective-c对象的问题:

typedef struct _BitmapFontChar {
    int charID;
    int x;
    int y;
    int width;
    int height;
    int xOffset;
    int yOffset;
    int xAdvance;
    Image * image; // Objective-C object in struct forbidden in ARC
    float scale;
} BitmapFontChar;

当我尝试使用__unsafe __unretained_时,它在ARC中编译得很好,但该项目不再起作用。当然,* image对象不会被保留,我的项目也会崩溃。

结构使用如下:

@interface BitmapFont : NSObject {

    GameController * sharedGameController;
    Image * image;
    BitmapFontChar * charsArray; // typedef struct
    int commonHeight;
    Color4f fontColor;
}​
...

charsArray = calloc(kMaxCharsInFont, sizeof(BitmapFontChar));

如何将此代码转换为保留*image对象的内容,但也可以在ARC中使用?

编辑: 好的,我使用了Jano建议使用CFTypeRef。我仍然在同一行代码中遇到相同的崩溃(EXC_BAD_ACCESS)。我想我没有正确使用CFBridgingRetain。下面是我的.h文件:

#import "Global.h"

@class Image;
@class GameController;

#define kMaxCharsInFont 223


typedef struct _BitmapFontChar {
    int charID;
    int x;
    int y;
    int width;
    int height;
    int xOffset;
    int yOffset;
    int xAdvance;
    CFTypeRef image;
    float scale;
} BitmapFontChar;

enum {
    BitmapFontJustification_TopCentered,
    BitmapFontJustification_MiddleCentered,
    BitmapFontJustification_BottomCentered,
    BitmapFontJustification_TopRight,
    BitmapFontJustification_MiddleRight,
    BitmapFontJustification_BottomRight,
    BitmapFontJustification_TopLeft,
    BitmapFontJustification_MiddleLeft,
    BitmapFontJustification_BottomLeft
};

@interface BitmapFont : NSObject {

    GameController *sharedGameController;
    Image *image;
    BitmapFontChar *charsArray;
    int commonHeight;
    Color4f fontColor;
}

@property(nonatomic, strong) Image *image;
@property(nonatomic, assign) Color4f fontColor;

- (id)initWithFontImageNamed:(NSString*)aFileName ofType:(NSString*)aFileType 
  controlFile:(NSString*)aControlFile scale:(Scale2f)aScale filter:(GLenum)aFilter;

- (id)initWithImage:(Image *)aImage controlFile:(NSString *)aControlFile 
  scale:(Scale2f)aScale filter:(GLenum)aFilter;

-(void)renderStringAt:(CGPoint)aPoint text:(NSString*)aText;

-(void)renderStringJustifiedInFrame:(CGRect)aRect justification:(int)aJustification 
  text:(NSString*)aText;

-(int)getWidthForString:(NSString*)string;
-(int)getHeightForString:(NSString*)string;

@end

以下是我的.m文件的一部分,其中包含发生崩溃的方法和代码行:

-(void)renderStringAt:(CGPoint)aPoint text:(NSString*)aText {
    float xScale = image.scale.x;
    float yScale = image.scale.y;

    for(int i=0; i<[aText length]; i++) {

        unichar charID = [aText characterAtIndex:i] - 32;

        int y = aPoint.y + (commonHeight * yScale) - (charsArray[charID].height 
            + charsArray[charID].yOffset) * yScale;
        int x = aPoint.x + charsArray[charID].xOffset;
        CGPoint renderPoint = CGPointMake(x, y);

        CFTypeRef vpImage = CFBridgingRetain(image); //???
        ((__bridge Image *)(charsArray[charID].image)).color = fontColor;//CRASH EXC_BAD_ACCESS

        [((__bridge Image *)(charsArray[charID].image)) renderAtPoint:renderPoint];

        aPoint.x += charsArray[charID].xAdvance * xScale;
    }
}

再次感谢您的建议!

3 个答案:

答案 0 :(得分:1)

使用__unsafe_unretained,并重新引入该特定结构域的显式保留/释放。据推测,这之前有用,所以没有理由今天无法工作。

当然,ARC不允许您致电-retain-release。但它确实允许你调用CFRetain()CFRelease(),它们在obj-c对象上调用时会做同样的事情。

或者,如果要将代码转换为Obj-C ++,可以在C ++结构中嵌入__strong对象,编译器将为您生成正确的析构函数。

答案 1 :(得分:0)

  

如何将此代码转换为保留*图像的代码   对象,但也可以在ARC中工作吗?

一种方法是将struct _BitmapFontChar转换为适当的Objective-C类。然后可以引用其他Obj-C对象。

答案 2 :(得分:-1)

Kevin和Caleb说的话。

因为我想自己尝试这个,这是CodeRunner的一个小例子:

#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
    @autoreleasepool {

        typedef struct _person {
            char name[25];
            CFTypeRef avatar;
        } person;

        NSObject *avatar = [NSObject new];
        CFTypeRef vpAvatar = CFBridgingRetain(avatar);
        person carol = { "Carol", vpAvatar }; 

        CFBridgingRelease(carol.avatar);
    }
}

CFRefType只是一个void *,它是__unsafe_unretained的替代品,CFBridging函数将一个Objc指针强制转换为Core Foundation(CFBridgingRetain)并返回(CFBridgingRelease)。

最简单的事情似乎是创建一个轻量级对象,让ARC处理它。