Нарисованный текст на CALayer не отображается или аварийно завершает работу во время выполнения

У меня есть CALayer, на котором я сначала рисую что-то, а потом текст:

- (void)drawInContext:(CGContextRef)context
{
    CGContextSaveGState(context);

    // draw things, everything displays correctly ...

    CGSize expectedCreditSize = [[gpData.credits stringValue] sizeWithFont:[UIFont 
                                                          systemFontOfSize:self.fontSize]];

    rect = CGRectMake(self.bounds.origin.x, self.bounds.size.height/2,
                      expectedCreditSize.width, expectedCreditSize.height);

    CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]);

    [self.creditString drawInRect:rect
                         withFont:[UIFont systemFontOfSize:self.fontSize]
                    lineBreakMode:NSLineBreakByWordWrapping
                        alignment:NSTextAlignmentRight];

    CGContextRestoreGState(context);
}

Вся графика отображается корректно, а вот текст нет. Что я делаю не так?

Я также пытался добавить CATextLayer в качестве подслоя, но поэтому во время выполнения получаю сообщение об ошибке.

CATextLayer *creditsTextLayer = [[CATextLayer alloc] init];
[creditsTextLayer setFrame:self.frame];
[creditsTextLayer setPosition:self.position];
[creditsTextLayer setString:self.creditString];
[creditsTextLayer setFontSize:self.fontSize];
[creditsTextLayer setAlignmentMode:kCAAlignmentLeft];
[creditsTextLayer setForegroundColor:[[UIColor whiteColor] CGColor]];
[self addSublayer:creditsTextLayer];

Единственное, что сработало, это это решение:

CGContextSelectFont (context,
                     "Helvetica-Bold",
                     self.fontSize,
                     kCGEncodingMacRoman);
CGContextSetTextDrawingMode (context, kCGTextFill);

CGContextSetRGBFillColor (context, 0, 1, 0, .5);
CGContextSetRGBStrokeColor (context, 0, 0, 1, 1);
CGContextShowTextAtPoint (context, 40, 0, self.creditString, 9);

Но это очень неудобно.

Есть ли у кого-нибудь идеи, что я могу сделать, чтобы одно из моих первых предложений сработало? Я что-то упустил для отображения текста?

Заранее спасибо!

изменить:

основываясь на ответе Шеймуса, теперь у меня это работает

- (void)drawInContext:(CGContextRef)context
{
    CGContextSaveGState(context);

    // draw things like circles and lines, 
    // everything displays correctly ...

    // now drawing the text
    UIGraphicsPushContext(context);

    CGSize expectedCreditSize = [[gpData.credits stringValue] sizeWithFont:[UIFont 
                                                          systemFontOfSize:self.fontSize]];

    rect = CGRectMake(self.bounds.origin.x, self.bounds.size.height/2,
                       expectedCreditSize.width, expectedCreditSize.height);

    CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]);

    [self.creditString drawInRect:rect
                         withFont:[UIFont systemFontOfSize:self.fontSize]
                    lineBreakMode:NSLineBreakByWordWrapping
                        alignment:NSTextAlignmentRight];

    UIGraphicsPopContext();
    CGContextRestoreGState(context);
}

Это означает, что я просто нажимаю и выдвигаю графический контекст для текста. Имеет ли это смысл? Почему это работает для рисования других вещей CGContext? Может кто объяснит…


person clash    schedule 04.04.2013    source источник
comment
Какую ошибку вы получаете с CATextLayer?   -  person daltonclaybrook    schedule 04.04.2013
comment
Он говорит, что ожидание слоя модели не копируется   -  person clash    schedule 04.04.2013
comment
Не могли бы вы опубликовать свой код инициализации CATextLayer?   -  person daltonclaybrook    schedule 04.04.2013
comment
Конечно! Поэтому я отредактировал свой вопрос.   -  person clash    schedule 04.04.2013
comment
является ли self.creditString типом NSString?   -  person daltonclaybrook    schedule 04.04.2013
comment
О да - это так. Все компилируется нормально, без предупреждений и ошибок.   -  person clash    schedule 04.04.2013


Ответы (1)


Обратите внимание, что -drawInRect:withFont:lineBreakMode:alignment: не принимает параметр CGContextRef — он обращается к «текущему» графическому контексту. Вы не показываете нам, как вы получили контекст, в который вы рисуете, но обычно этот метод NSString будет использоваться в методе -drawRect с полученным контекстом, например:

CGContextRef context = UIGraphicsGetCurrentContext();

Вы можете сделать свой контекст «текущим контекстом» с помощью UIGraphicsPushContext() (но убедитесь, что вы также вызываете UIGraphicsPopContext()):

- (void)drawInContext:(CGContextRef)context
{
    UIGraphicsPushContext(context);
    CGContextSaveGState(context);

    // draw things, everything displays correctly ...

    CGSize expectedCreditSize = [[gpData.credits stringValue] sizeWithFont:[UIFont 
                                                          systemFontOfSize:self.fontSize]];

    rect = CGRectMake(self.bounds.origin.x, self.bounds.size.height/2,
                      expectedCreditSize.width, expectedCreditSize.height);

    CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]);

    [self.creditString drawInRect:rect
                         withFont:[UIFont systemFontOfSize:self.fontSize]
                    lineBreakMode:NSLineBreakByWordWrapping
                        alignment:NSTextAlignmentRight];

    CGContextRestoreGState(context);
    UIGraphicsPopContext();
}
person Seamus Campbell    schedule 04.04.2013
comment
Спасибо. Я попробую это завтра! Мне просто интересно, потому что все остальное, что я рисовал в этом контексте раньше, показано (линии, круги)... - person clash; 04.04.2013
comment
Я только что попробовал ваше решение и получил немного модифицированную версию для работы. Я обновил свой вопрос выше. Может быть, вы можете взглянуть на это, пожалуйста? Я хотел бы понять слои и рисунок на них. - person clash; 05.04.2013
comment
Извините, я попытался объяснить, почему в первом абзаце. Другие методы работали без пары push/pop, потому что это функции, которые обращаются к определенному контексту — это первый аргумент, который они принимают. -drawInRect:withFont:lineBreakMode:alignment: отличается, он обращается к неявному контексту — тому, который находится поверх UIGraphics стека текущего контекста. Вы можете легко определить, что это так, заметив, что эта функция не принимает контекст в качестве параметра. Вот почему CGContextShowTextAtPoint() сработало для вас; он принимает явный контекст. - person Seamus Campbell; 05.04.2013
comment
Это имеет смысл. Большое спасибо! - person clash; 07.04.2013