So, I have the following code (simplified for demonstration purposes) to create a CTParagraphStyle
:
var minimumLineHeight: CGFloat = 14
var maximumLineHeight: CGFloat = 14
var lineSpacingAdjustment: CGFloat = 10
var alignment: CTTextAlignment = .left
let paragraphStyle = CTParagraphStyleCreate([
CTParagraphStyleSetting(spec: .minimumLineHeight, valueSize: MemoryLayout<CGFloat>.size, value: &minimumLineHeight),
CTParagraphStyleSetting(spec: .maximumLineHeight, valueSize: MemoryLayout<CGFloat>.size, value: &maximumLineHeight),
CTParagraphStyleSetting(spec: .lineSpacingAdjustment, valueSize: MemoryLayout<CGFloat>.size, value: &lineSpacingAdjustment),
CTParagraphStyleSetting(spec: .alignment, valueSize: MemoryLayout<CTTextAlignment>.size, value: &alignment)
], 4)
After upgrading to Swift 5.2, I get the warning that Inout expression creates a temporary pointer, but argument 'value' should be a pointer that outlives the call to 'init(spec:valueSize:value:)'.
As far as I can understand I need to replace my code with the following monstrosity:
let minimumLineHeight: CGFloat = 14
let maximumLineHeight: CGFloat = 14
let lineSpacingAdjustment: CGFloat = 10
let alignment: CTTextAlignment = .left
let paragraphStyle: CTParagraphStyle = withUnsafeBytes(of: minimumLineHeight) { minimumLineHeightBytes in
withUnsafeBytes(of: maximumLineHeight) { maximumLineHeightBytes in
withUnsafeBytes(of: lineSpacingAdjustment) { lineSpacingAdjustmentBytes in
withUnsafeBytes(of: alignment) { alignmentBytes in
CTParagraphStyleCreate([
CTParagraphStyleSetting(spec: .minimumLineHeight, valueSize: MemoryLayout<CGFloat>.size, value: minimumLineHeightBytes.baseAddress!),
CTParagraphStyleSetting(spec: .maximumLineHeight, valueSize: MemoryLayout<CGFloat>.size, value: maximumLineHeightBytes.baseAddress!),
CTParagraphStyleSetting(spec: .lineSpacingAdjustment, valueSize: MemoryLayout<CGFloat>.size, value: lineSpacingAdjustmentBytes.baseAddress!),
CTParagraphStyleSetting(spec: .alignment, valueSize: MemoryLayout<CTTextAlignment>.size, value: alignmentBytes.baseAddress!)
], 4)
}
}
}
}
First, is that correct? Is there a better way to write it? I’m assuming that the pointers don’t need to outlive the call to CTParagraphStyleCreate
but this isn't actually documented anywhere.
Second, was this always undefined behavior? When is it ever safe to use &
to create a pointer to something?