我正在尝试CGPattern
在Swift中使用彩色图案。Apple在Quartz 2D编程指南的“
绘画彩色图案”部分中提供了一个不错的Objective-
C示例。但是,从Objective-C转换所有语法并非易事。另外,我想info
在绘图回调中使用该参数,并且没有这样做的示例。
这是我的第一次尝试:
class SomeShape {
func createPattern() -> CGPattern? {
let bounds = CGRect(x: 0, y: 0, width: someWidth, height: someHeight)
let matrix = CGAffineTransform.identity
var callbacks = CGPatternCallbacks(version: 0, drawPattern: nil, releaseInfo: nil)
let res = CGPattern(info: nil, bounds: bounds, matrix: matrix, xStep: bounds.width, yStep: bounds.height, tiling: .noDistortion, isColored: true, callbacks: &callbacks)
return res
}
}
显然,这需要一个合适的drawPattern
参数值CGPatternCallbacks
,我需要将其self
作为info
参数传递给CGPattern
初始化程序。
完成此操作的正确语法是什么?
正如您在回答中所说,CGPatternDrawPatternCallback
定义为:
typealias CGPatternDrawPatternCallback =
@convention(c) (UnsafeMutableRawPointer?, CGContext) -> Void
该@convention(c)
属性(似乎只显示在生成的标头中)意味着所使用的函数值必须与C兼容,因此不能捕获任何上下文(因为C函数值只不过是指向函数的原始指针,所以不要t存储其他上下文对象)。
因此,如果您想在函数中使用上下文,则需要将自己的上下文传递UnsafeMutableRawPointer?
给Initializer的info:
参数。然后在调用时将其作为给定绘制模式函数的第一个参数传递。CGPattern
为了传递self
给该参数,您可以使用Unmanaged
。这使您可以在引用和不透明指针之间进行转换,并且与不同unsafeBitCast
,它还可以让您控制引用的内存管理。
鉴于我们不能保证of的调用者createPattern()
会self
保留,我们 不能
仅将其传递给info:
参数而不自己保留它。如果传递时没有保留(例如,使用unsafeBitCast
),然后在绘制图案之前将其释放-
尝试在绘图回调中使用悬空指针时,您将得到 未定义的行为 。
与Unmanaged
:
您可以将引用作为+1保留的不透明指针传递给 passRetained(_:).toOpaque()
您可以使用以下命令从此指针获取引用fromOpaque(_:).takeUnretainedValue()
(实例将保持不变)
然后,您可以通过使用+1保留fromOpaque(_:).release()
。CGPattern
释放时,您需要执行此操作。
例如:
class SomeShape {
// the bounds of the shape to draw
let bounds = CGRect(x: 0, y: 0, width: 40, height: 40)
func createPattern() -> CGPattern? {
var callbacks = CGPatternCallbacks(version: 0, drawPattern: { info, ctx in
// cast the opaque pointer back to a SomeShape reference.
let shape = Unmanaged<SomeShape>.fromOpaque(info!).takeUnretainedValue()
// The code to draw a single tile of the pattern into "ctx"...
// (in this case, two vertical strips)
ctx.saveGState()
ctx.setFillColor(UIColor.red.cgColor)
ctx.fill(CGRect(x: 0, y: 0,
width: shape.bounds.width / 2, height: shape.bounds.height))
ctx.setFillColor(UIColor.blue.cgColor)
ctx.fill(CGRect(x: 20, y: 0,
width: shape.bounds.width / 2, height: shape.bounds.height))
ctx.restoreGState()
}, releaseInfo: { info in
// when the CGPattern is freed, release the info reference,
// consuming the +1 retain when we originally passed it to the CGPattern.
Unmanaged<SomeShape>.fromOpaque(info!).release()
})
// retain self before passing it off to the info: parameter as an opaque pointer.
let unsafeSelf = Unmanaged.passRetained(self).toOpaque()
return CGPattern(info: unsafeSelf, bounds: bounds, matrix: .identity,
xStep: bounds.width, yStep: bounds.height,
tiling: .noDistortion, isColored: true, callbacks: &callbacks)
}
}
另外,如果您想要一个更好的解决方案,则SomeShape
可以将其设置为struct
。然后,在创建模式时,您可以将其包装到一个Context
堆分配的框中,然后再将其传递给info:
参数:
struct SomeShape {
// the bounds of the shape to draw
let bounds = CGRect(x: 0, y: 0, width: 40, height: 40)
func createPattern() -> CGPattern? {
final class Context {
let shape: SomeShape
init(_ shape: SomeShape) { self.shape = shape }
}
var callbacks = CGPatternCallbacks(version: 0, drawPattern: { info, ctx in
// cast the opaque pointer back to a Context reference,
// and get the wrapped shape instance.
let shape = Unmanaged<Context>.fromOpaque(info!).takeUnretainedValue().shape
// ...
}, releaseInfo: { info in
// when the CGPattern is freed, release the info reference,
// consuming the +1 retain when we originally passed it to the CGPattern.
Unmanaged<Context>.fromOpaque(info!).release()
})
// wrap self in our Context box before passing it off to the info: parameter as a
// +1 retained opaque pointer.
let unsafeSelf = Unmanaged.passRetained(Context(self)).toOpaque()
return CGPattern(info: unsafeSelf, bounds: bounds, matrix: .identity,
xStep: bounds.width, yStep: bounds.height,
tiling: .noDistortion, isColored: true, callbacks: &callbacks)
}
}
现在,这也可以解决任何保留周期问题。
问题内容: 我正在尝试使用AWS Lambda Python(Python初学者)启动并运行,但是在包含MySQL依赖项时遇到了一些问题。我试图按照指示在这里我的Mac上。 对于第3步,我在项目的根目录执行命令遇到一些问题 错误: 例外:追溯(最近一次通话最近):文件“ /Library/Python/2.7/site- packages/pip-1.5.6-py2.7.egg/pip/basec
我有一个通过http承载图像的地理服务器。我的客户端站点使用https。我一直在使用openlayers,一切都很好。现在我正试图转移到cesiumjs,我在IE或Edge中没有得到任何图像(不幸的是,我无法测试其他浏览器)。如果使用bing地图,我可以在我的客户机中获取图像,因此客户机代码在其他情况下是可用的。在浏览器控制台中,我看到: SEC7117:网络请求超文本传输协议://[myserv
我有一个SpringBoot应用程序,它运行默认的嵌入式tomcat(带有TomcatJDBC连接池)。这是生产和运行良好。我使用mysql作为我的数据库。 我现在正在我的测试环境中做一些压力测试,并试图看看如果我从嵌入式Tomcat切换到嵌入式Undertow,我是否会得到任何明显的好处。人们声称通过这样做可以显著提高吞吐量,这是由于潜在请求处理的异步性质。 我知道如何排除tomcat并将und
在嵌入式TomEE容器中运行Arquillian测试时,我得到了以下错误
问题内容: 我试图建立一个对象,使其具有封装的$ .getJSON方法。这是我的设置: 现在的问题似乎是我没有访问有意义的getJSON回调函数中的“ this”。 这种功能是否有解决方法,或者我只是在想完全错误的方式?我以前只真正使用过PHP OO编码,所以JS OO对我来说有点新。 我尝试过的其他事情是: 但是, 问题答案: 您的第一次尝试已经结束,但是正如您所说的,您无法在回调内部进行访问,
问题内容: 我正在尝试将React-redux与Typescript一起使用,当我尝试使用connect()和mapStateToProps注入道具时遇到类型错误。 我的组件如下所示: 商店看起来像这样 最后,我将类型定义为: 当我尝试编译代码时,出现以下错误: 有趣的是,即使代码抛出类型错误,它仍然可以正常工作。同样,将组件的prop接口更改为any也可以解决该问题。似乎类型系统无法理解这两个映