На iOS, почему рисунок UIBezierPath не требует контекста?

В iOS мы можем нарисовать строку в drawRect с помощью

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginPath (context);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 100, 100);
CGContextStrokePath(context);

но мы также можем нарисовать прямоугольник, если мы удалим вышеуказанный код и просто используем:

UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];
[path stroke];

Два связанных вопроса:

1) Почему не нужно UIBezierPath получать или использовать текущий контекст?

2) Что делать, если у меня есть два контекста: один для экрана, а один - растровый контекст, а затем как определить, какой контекст рисовать для UIBezierPath? Я думал, что это может быть UIGraphicsSetCurrentContext, но этого не существует.

Ответ 1

UIBezierPath использует контекст. Он использует текущий графический контекст UIKit. Это то же самое, что вы уже получаете с UIGraphicsGetCurrentContext().

Если вы хотите, чтобы UIBezierPath использовал другой контекст, вы можете использовать UIGraphicsPushContext(), но вы должны помнить, что используете UIGraphicsPopContext(), когда вы закончите.

Ответ 2

Я подумал, что было бы полезно упомянуть, что CGContextFillRect ~ 8.5x быстрее, чем использование UIBezierPath из того, что я могу сказать (в случае, если производительность является фактором и предполагает, что вам не нужно использовать UIBezierPath для более сложного рисования).

Я добавил несколько примеров для примера Apple HazardMap (http://developer.apple.com/library/ios/#samplecode/HazardMap/Introduction/Intro.html), а время в мс на прямой составляет ~ 0,00064 мс/прямой для подхода CGContextFillRect против ~ 0,00543 мс/прямоугольник для подхода UIBezierPath, предположительно b/c, для последнего требуется больше служебных служебных сообщений.

то есть. Я сравниваю использование

CGContextFillRect(ctx, boundaryCGRect);

по сравнению с использованием

UIBezierPath* path = [UIBezierPath bezierPathWithRect:boundaryCGRect];
[path fill];

во внутреннем цикле в HazardMapView (плюс вышеупомянутые изменения для push/pop контекста, который передается в HazardMapView drawMapRect: zoomScale: inContext:).

ЕТА

Ответ 3

В iOS мы можем нарисовать строку в drawRect, используя

Я выделил важную часть этого утверждения. Внутри drawRect: контекст уже настроен для вас с помощью UIKit, и любые ориентированные на объект чертежные инструкции идут непосредственно в этот контекст. UIBezierPath действительно использует этот контекст, его просто не нужно передавать явно.

В Cocoa Коснитесь, всегда должен быть контекст чертежа (в этом случае контекст будет в конечном итоге нарисован на экране). Если вы не были внутри drawRect:, вам нужно создать контекст самостоятельно.

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginPath (context);
CGContextMoveToPoint(context, 0, 0);

Обратите внимание, что первый вызов функции Получить CurrentContext(). Когда вы используете интерфейс функционального рисования CoreGraphics, вам нужно передать контекст в каждую функцию, но вы не создаете его здесь, вы просто извлекаете тот, который уже существует.

Графические контексты находятся в стеке. Если вы хотите врисовать контекст, который вы создали, вы нажимаете его на стек с помощью UIGraphicsPushContext() (как уже упоминал Кевин), затем возвращайтесь к предыдущему.