【问题标题】:Creating a window graphics context for a CGLayer in iOS outside drawRect: of UIView在 UIView 的 drawRect: 之外为 iOS 中的 CGLayer 创建窗口图形上下文
【发布时间】:2011-03-01 23:30:39
【问题描述】:

UIView 在调用自定义drawRect: 方法之前创建一个窗口图形上下文,因此在该方法中我可以获得图形上下文。但是,似乎 唯一的方法 在 iOS 中获取窗口图形上下文,因此我只能在 UIView 对象的自定义 drawRect: 方法中基于窗口图形上下文制作 CGLayer 对象。

但是,我可能希望模型对象包含 CGLayer 对象,该对象是使用模型对象本身创建的,后来很多视图使用该层将其内容绘制到自己的视图上。一个人可能会创建一个位图图形上下文来创建一个 CGLayer,但是使用 CGLayer 对象在屏幕上绘制的所有内容都将具有位图上下文的特征,正如 Apple 的文档所说,使用 CGLayer 对象进行绘制受限于图形上下文的类型用于创建图层。

所以我的问题是,真的不可能在drawRect: 之外创建一个窗口图形上下文来基于它创建一个 CGLayer 对象。或者,有没有更好的方法来创建和存储一个 CGLayer 对象以供多个视图共享的屏幕绘图?或者出于我没有意识到的原因,在 UIView 对象之外拥有这样一个共享的 CGLayer 对象是完全错误的想法吗?

【问题讨论】:

    标签: iphone ios


    【解决方案1】:

    是的,您可以从位图为 CALayer 创建绘图上下文。

    但是 CGLayer 的内容需要一个支持位图,因为它在绘制时不保存符号(与分辨率无关)绘图矢量,只保存结果像素。因此,要么创建支持位图,要么使用 UIView 提供的位图,或者在需要时从自己的命令列表中重新创建/重绘位。

    【讨论】:

    • 似乎根本不可能创建位图或 pdf 以外的窗口图形上下文。也许苹果是愚蠢的,或者需求并不像我想象的那么明显。不过还是谢谢你的回答!
    【解决方案2】:

    以下 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)
        }
    }
    

    【讨论】:

    • UIGraphicsGetCurrentContext() 从 viewWillAppear() 调用时似乎返回 nil
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 2018-11-22
    相关资源
    最近更新 更多