I focus on a project to add image support based on OmniGroup's rtf editor.I met the problem when I use CTFramesetterCreateWithAttributedString
, and it receives
EXC_BAD_ACCESS
which is caused by a zombie object.
For simplicity, I get the NSAttributedString
from a rtfd file which only has a photo. I add the method to parser the image tag on iOS based on the Omni's sample. And the part to create the NSAttributedString
is followed by this tutorial from raywenderlich, and looks like:
CTRunDelegateCallbacks callbacks;
callbacks.version = kCTRunDelegateCurrentVersion;
callbacks.getAscent = ascentCallback;
callbacks.getDescent = descentCallback;
callbacks.getWidth = widthCallback;
callbacks.dealloc = deallocCallback;
CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks, imgAttr);
NSDictionary *imgAttr = [NSDictionary dictionaryWithObjectsAndKeys:imgWidth,kImageWidth,imgHeight,kImageHeight, nil];//recored the width and height
NSDictionary *attrDictionaryDelegate = [NSDictionary dictionaryWithObjectsAndKeys:(id)delegate, (NSString*)kCTRunDelegateAttributeName,nil];
[_attributedString appendString:@" " attributes:attrDictionaryDelegate];
CFRelease(delegate);
here appendString:attributes:
is provided by Omni and is a category for NSMutableAttributedString
:
- (void)appendString:(NSString *)string attributes:(NSDictionary *)attributes;
{
NSAttributedString *append;
append = [[NSAttributedString alloc] initWithString:string attributes:attributes];
[self appendAttributedString:append];
[append release];
}
In the Parser class I test CTFramesetterCreateWithAttributedString
and it creates successfully and no memory problem happens. However, when I call CTFramesetterCreateWithAttributedString
in my view class, it receives the EXC_BAD_ACESS
problem. I send the CTFramesetterCreateWithAttributedString
to my view in the viewDidLoad:
NSArray *arr = [OUIRTFReader parseRTFString2:rtfString];
self.editFrame.attributedText = [arr objectAtIndex:0];
//for OUIRTFReader
+ (NSArray *)parseRTFString2:(NSString *)rtfString
{
OUIRTFReader *parser = [[self alloc] _initWithRTFString:rtfString];
NSMutableArray *temp = [NSMutableArray arrayWithCapacity:1];
NSAttributedString *tempAstr = [[NSAttributedString alloc] initWithAttributedString:parser.attributedString];
[temp addObject:tempAstr];
[tempAstr release];
if (parser.zjImageArray) {
[temp addObject:parser.zjImageArray];
}
[parser release];
}
here editFrame is ivar of OUIEditableFrame
provided by OmniFramework.
After that, in the layoutSubview:
of OUIEditableFrame
, CTFramesetterCreateWithAttributedString
failed. Profiling with instrument, it points there is a zombie object in :
NSDictionary *imgAttr = [NSDictionary dictionaryWithObjectsAndKeys:imgWidth,kImageWidth,imgHeight,kImageHeight, nil];
It demonstrates that
An Objective-C message was sent to a deallocated object(zombie) at address
I'm not so familiar with core foundation like as UIKit or others. So I'd like to know what's wrong with the method to create a attributed string for image with CTRunDelegateRef in my code?
Thanks!