Создание контекста оконной графики для CGLayer в iOS вне drawRect: of UIView

UIView создает контекст графики окна перед вызовом настраиваемого метода drawRect:, поэтому внутри метода я могу получить контекст графики. Однако кажется, что это единственный способ получить контекст оконной графики в iOS, поэтому я могу создать объект CGLayer на основе контекста оконной графики только в пользовательском методе drawRect: объекта UIView.

Однако я мог бы захотеть, чтобы объект модели содержал объект CGLayer, который создается с самим объектом модели, а позже многие представления используют этот слой для рисования своего содержимого в своих собственных представлениях. Можно создать контекст растровой графики для создания CGLayer, но тогда все, что нарисовано на экране с использованием объекта CGLayer, будет иметь характеристики контекста растрового изображения, поскольку в документах Apple говорится, что рисование с помощью объекта CGLayer ограничено типом графического контекста. используется для создания слоя.

Итак, мой вопрос: действительно ли невозможно создать контекст оконной графики вне drawRect:, чтобы создать объект CGLayer на его основе. Или есть лучший способ создать и сохранить объект CGLayer для рисования на экране, который может использоваться несколькими видами? Или это совершенно ложная идея иметь такой общий объект CGLayer вне объекта UIView по непонятной мне причине?


person MHC    schedule 01.03.2011    source источник


Ответы (2)


Да, вы можете создать контекст рисования для CALayer из растрового изображения.

Но для содержимого CGLayer требуется резервное растровое изображение, поскольку оно не сохраняет символические (независимые от разрешения) векторы рисования при рисовании, а только результирующие пиксели. Таким образом, вы либо создаете резервное растровое изображение, либо используете одноручное изображение с помощью UIView, либо при необходимости воссоздаете / перерисовываете биты из своего собственного списка команд.

person hotpaw2    schedule 02.03.2011
comment
Кажется, просто невозможно создать контекст оконной графики, отличный от растрового или pdf. Возможно, Apple глупа или необходимость не так очевидна, как я думал. Спасибо за ответ! - person MHC; 03.03.2011

Следующие примеры в Swift показывают, как я сделал то, что задает исходный вопрос, как в iOS, так и в OSX.

Примечание: когда вы создаете CGLayer, предоставленный вами графический контекст используется исключительно в качестве ссылки для инициализации слоя. В него не отправляется никакой контент или что-либо еще - это просто должен быть правильный ТИП контекста, чтобы API знал, какой уровень создать.

В этом примере я создаю CGLayer в контроллере представления и рисую на нем. Затем я визуализирую его на экране с помощью метода drawRect () представления.


пример iOS

Контроллер представления

import UIKit

class ViewController: UIViewController {
    @IBOutlet var myView: MyView!

    override func viewWillAppear(animated: Bool) {
        // get the current graphics context - any context relevant to the screen 
        // will do for this purpose
        let currentGraphicsContext = UIGraphicsGetCurrentContext()

        // create a GCLayer with low level properties appropriate to the device 
        // screen and a size of 100 x 100
        // this process doesn't send any content to windowGraphicsContext, it just 
        // copies some of the low level fields about the screen
        let newLayer = CGLayerCreateWithContext(currentGraphicsContext, 
                                                CGSize(width: 100, height: 100), 
                                                nil)

        // store a reference to the layer in a property of the view so that the 
        // view can display it
        myView.layerRef = newLayer

        // create a new graphics context for the layer so that we can draw on it
        let myLayerContext = CGLayerGetContext(newLayer)

        // draw some content on the layer
        CGContextSetFillColorWithColor(myLayerContext, UIColor.redColor().CGColor)
        CGContextFillRect(myLayerContext, 
                          CGRect(x: 0, y: 0, width: 100, height: 50))
        CGContextSetFillColorWithColor(myLayerContext, UIColor.blueColor().CGColor)
        CGContextFillRect(myLayerContext, 
                          CGRect(x: 0, y: 50, width: 50, height: 50))
    }
}

Подкласс UIView

import UIKit

class MyView: UIView {

    // a reference to the layer created by the view controller
    var layerRef: CGLayer?

    override func drawRect(rect: CGRect) {
        // get a graphics context for the view
        let myViewGraphicsContext = UIGraphicsGetCurrentContext()

        // draw the layer into the view
        CGContextDrawLayerAtPoint(myViewGraphicsContext, 
                                  CGPoint(x: 20 , y: 20), 
                                  self.layerRef)
    }
}

Пример OSX

Контроллер представления

import Cocoa

class ViewController: NSViewController {
    @IBOutlet var myView: MyView!

    override func viewWillAppear() {
        // get a graphics context for the window that contains the view - any 
        // context relevant to the screen will do
        let windowGraphicsContext = NSGraphicsContext(window: myView.window!)

        // create a GCLayer with low level properties appropriate to the device 
        // screen and a size of 100 x 100
        // this process doesn't send any content to windowGraphicsContext, it just 
        // copies some of the low level fields about the screen
        let newLayer = CGLayerCreateWithContext(windowGraphicsContext.CGContext, 
                     CGSize(width: 100, height: 100), nil)

        // store a reference to the layer in a property of the view, so that the 
        // view can display it
        myView.layerRef = newLayer

        // create a new graphics context for the layer so that we can draw on it
        let myLayerContext = CGLayerGetContext(newLayer)

        // do some drawing on the layer
        CGContextSetFillColorWithColor(myLayerContext, NSColor.redColor().CGColor)
        CGContextFillRect(myLayerContext, 
                          CGRect(x: 0, y: 0, width: 100, height: 50))
        CGContextSetFillColorWithColor(myLayerContext, NSColor.blueColor().CGColor)
        CGContextFillRect(myLayerContext, 
                          CGRect(x: 0, y: 50, width: 50, height: 50))
    }
}

Подкласс NSView

import Cocoa

class MyView: NSView {

    // a reference to the layer created by the view controller
    var layerRef: CGLayer?

    override func drawRect(dirtyRect: NSRect) {    
        super.drawRect(dirtyRect)

        // get a graphics context for the view
        let graphicsContext = NSGraphicsContext.currentContext()?.CGContext

        // draw the layer into the view
        CGContextDrawLayerAtPoint(graphicsContext, 
                                  CGPoint(x: 20 , y: 20), 
                                  self.layerRef)
    }
}
person Martin CR    schedule 20.07.2016
comment
UIGraphicsGetCurrentContext (), похоже, возвращает ноль при вызове из viewWillAppear () - person user3717478; 06.08.2017