Why can't I release my CTFramesetter without the app crashing?
-
28-09-2019 - |
Question
I'm building an iPad app which renders pages of text from an NSAttributedString. I create a framesetter like this:
- (void)renderTextFromAttributedString:(NSAttributedString *)string
{
CFAttributedStringRef attrString = (CFAttributedStringRef)string;
framesetter = CTFramesetterCreateWithAttributedString(attrString);
CFRelease(attrString);
... then the code adds new page views, one by one, and passes the framesetter pointer off to each one to render each page, until there are no characters left:
- (void)drawNewPage
{
CTSinglePageView *newPage = [[CTSinglePageView alloc] initWithFrame:newFrame];
newPage.delegate = self;
[newPage renderWithFramesetter:framesetter fromIndex:currentIndex margins:self.margins];
[self addSubview:newPage];
[newPage release];
currentPage ++;
... etc etc. Now this all works great, rendering the pages and showing the formatted text perfectly. However, at the end of the render process, I've still got a CTFramesetter which needs clearing, so I can build the next set of pages. However, if I do
if(framesetter) CFRelease(framesetter);
at the end of the process, the CTFramesetter is released (obviously) and the program crashes! BUT... If I don't release the framesetter, I eventually get rather large memory leaks and the program bails out.
Why is the release causing a crash? With NSZombieEnabled turned on, the error message I get is:
* -[NSConcreteAttributedString release]: message sent to deallocated instance 0xed20270
Any help given is of course greatly received! We are currently up against a deadline here, if I could add a bounty now I would! Anyone with a good answer will be rewarded a bounty after the 2 day window has elapsed. :-)
Solution
Are you sure you're supposed to be releasing attrString? That doesn't look right. I wonder if that's causing the crash later when releasing framesetter.