Swift新手求助:实现格式对齐的收据打印(修复字符串长度变化导致的对齐失效问题)
解决Swift收据打印的三列对齐问题
看起来你遇到了固定宽度填充导致的对齐失效问题——当左侧名称长度变化时,原来的填充逻辑没办法维持三列的整齐布局。咱们来调整一下代码,实现像目标收据那样的左对齐序号、左对齐服务名称、右对齐金额的效果,同时支持自适应列宽,确保不管内容长短都能对齐。
问题根源分析
你当前的formattedString函数把金额和序号用同一个填充逻辑处理,没有明确划分列的宽度和对齐方式,一旦左侧名称长度超过设定的width,后续的空格填充就会混乱,自然没法保持对齐。
解决方案:分列控制对齐与宽度
我们可以重新设计格式化函数,明确划分三列的职责:
- 序号列:固定宽度,左对齐
- 服务名称列:可自适应最大宽度,左对齐
- 金额列:固定宽度,右对齐
同时要注意:打印收据必须使用等宽字体(比如Courier New),否则即使字符串长度一致,非等宽字体的字符宽度不同,对齐效果还是会失效。
改进后的代码示例
// 格式化单行收据内容 func formattedReceiptLine(serialNumber: String, serviceName: String, amount: String, serialColumnWidth: Int = 3, amountColumnWidth: Int = 8) -> String { // 序号左对齐,填充到指定宽度 let paddedSerial = serialNumber.padding(toLength: serialColumnWidth, withPad: " ", startingAt: 0) // 服务名称暂不固定宽度,后续统一计算最大宽度 let paddedName = serviceName // 金额右对齐:在前面填充空格,确保总长度等于金额列宽度 let paddedAmount = String(repeating: " ", count: max(0, amountColumnWidth - amount.count)) + amount return paddedSerial + paddedName + paddedAmount } // 生成完整收据内容 func generateReceipt(items: [(serial: String, name: String, amount: String)]) -> String { // 计算服务名称的最大长度,加2作为列宽(预留空格间距) let maxNameLength = items.map { $0.name.count }.max() ?? 0 let nameColumnWidth = maxNameLength + 2 // 格式化每一行,并统一调整名称列的宽度 let formattedLines = items.map { item in let paddedName = item.name.padding(toLength: nameColumnWidth, withPad: " ", startingAt: 0) return item.serial.padding(toLength: 3, withPad: " ", startingAt: 0) + paddedName + String(repeating: " ", count: max(0, 8 - item.amount.count)) + item.amount } return formattedLines.joined(separator: "\n") } // 使用示例 let receiptItems = [ ("1", "MAXIS Hotlink", "25.00"), ("0", "DIGI Prepaid", "5.00"), ("2", "CELCOM Xpax", "5.00"), ("3", "U Mobile Postpaid Plus", "45.90") // 测试长名称 ] let receipt = generateReceipt(items: receiptItems) print(receipt)
代码说明
- 分列处理:每一列都有独立的对齐逻辑,序号和名称左对齐填充,金额右对齐填充,确保每列的边界清晰。
- 自适应列宽:
generateReceipt函数会自动计算所有服务名称的最大长度,动态调整名称列的宽度,避免短名称浪费空间、长名称溢出的问题。 - 等宽字体要求:打印时务必设置打印机字体为等宽字体,比如
UIFont(name: "CourierNewPSMT", size: 12),这是保证对齐效果的关键。
这样调整后,不管你的服务名称长短如何,三列内容都会整齐对齐,和目标收据的效果一致。
内容的提问来源于stack exchange,提问作者Prissy Eve
相关产品推荐
相关产品推荐

