问题
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!
回答1:
CTRunDelegateCreate create a delegate with an arbitrary context pointer (void *). That means the dictionary imgAttr isn't retained by the delegate.
You need to retain the context dictionary when creating the delegate and release it in the dealloc callback.
来源:https://stackoverflow.com/questions/8558513/memory-management-for-ctrundelegateref-iphone