Swift中调用Cairo.Context.setFont及扩展CairoGraphics类的问题
关于Swift Graphics模块的两个问题
我的Swift Vapor后端代码使用了Graphics模块,该模块依赖Cairo模块。Graphics模块中的CairoGraphics类初始化代码如下:
import Cairo import Utils public class CairoGraphics: Graphics { private let context: Cairo.Context // 该属性为私有,外部代码无法访问 private let image: Image deinit { flush() } public init(fromImage image: Image) { context = Cairo.Context(surface: image.surface) // 在此处创建 self.image = image } }
初始化时会创建一个Cairo.Context对象,该对象有一个设置自定义渲染字体的方法:
public func setFont(face: (family: String, slant: Cairo.FontSlant, weight: Cairo.FontWeight))
我遇到两个问题:
- 如何从外部代码调用这个
setFont方法?CairoGraphics没有对应的公开属性,只有上述私有属性。 - 我能否给
CairoGraphics添加公开方法?还是说CairoGraphics只有二进制代码,当前文件仅为接口,添加新方法不会生效?
我尝试通过扩展解决,但出现错误:
'context' is inaccessible due to 'private' protection level
扩展代码如下:
extension CairoGraphics { func getContext() -> Cairo.Context { return context } }
或者我是否应该fork该仓库、修改代码后使用自己的版本?
解答
问题1:调用setFont方法的可行方案
由于context是CairoGraphics的私有属性,外部代码(包括类扩展)无法直接访问,所以你没办法直接拿到这个对象调用setFont。现有情况下有两个方向可选:
- 先检查模块是否提供了间接设置字体的公开API(比如父类
Graphics有没有相关方法),优先使用官方暴露的接口; - 修改
CairoGraphics源码,要么将context的访问级别改为internal(同模块可见)或public,要么给CairoGraphics添加一个公开的setFont方法,内部转发调用context.setFont,示例代码:public class CairoGraphics: Graphics { // ... 原有代码 ... public func setFont(face: (family: String, slant: Cairo.FontSlant, weight: Cairo.FontWeight)) { context.setFont(face: face) } }
问题2:能否给CairoGraphics添加公开方法?
这取决于你使用的Graphics模块类型:
- 如果是源码依赖(比如通过Swift Package Manager拉取的源码),你可以给
CairoGraphics写扩展,但因为context是私有属性,扩展无法访问该成员,只能添加不依赖内部私有逻辑的方法; - 如果是二进制依赖(比如预编译框架),你只能看到公开接口,无法访问内部私有成员,扩展同样无法调用私有属性的方法,这种情况下添加的扩展对你当前需求没有帮助。
最终建议
最直接有效的方式是fork该仓库,修改CairoGraphics代码:要么暴露context的访问权限,要么添加封装好的setFont公开方法,之后在你的项目中依赖自己fork后的仓库版本。如果你的改动具备通用性,还可以给原仓库提交Pull Request贡献代码。
内容的提问来源于stack exchange,提问作者János
相关产品推荐
相关产品推荐

