Skip to content

Swift SDK

The Swift SDK is designed for modern iOS and macOS applications and connects to printers over Bluetooth Low Energy (BLE).

Download the frameworks from GitHub: Package Center

Required frameworks:

  • adapter.framework - Device adapter
  • father.framework - Core framework

Optional frameworks:

  • cpcl.framework - CPCL commands
  • esc.framework - ESC commands
  • tspl.framework - TSPL commands

Create YourProject-Bridging-Header.h:

#import <adapter/adapter.h>
#import <father/father.h>
#import <tspl/tspl.h>
#import <cpcl/cpcl.h>
#import <esc/esc.h>

Set the Objective-C Bridging Header path in Build Settings.

import Foundation
import CoreBluetooth
class PrinterManager: NSObject {
private var lifecycle: Lifecycle?
private var connectedPeripheral: CBPeripheral?
func connect(device: CBPeripheral) {
lifecycle = Lifecycle()
lifecycle?.connectedDevice(device)
connectedPeripheral = device
}
func disconnect() {
connectedPeripheral = nil
lifecycle = nil
}
}

ESC commands are widely used by thermal receipt printers. See the ESC command reference for details.

private var escCommand: AYEscCommand?
func setupESC() {
escCommand = AYEscCommand()
}
func printReceipt() {
guard let esc = escCommand else { return }
// 1. Wake the printer
esc.wake()
// 2. Enable the printer
esc.enable()
// 3. Print an image
if let image = UIImage(named: "receipt") {
esc.image(image, compress: false, mode: .normal)
}
// 4. Position the paper (Not needed for continuous paper)
esc.position()
// 5. End the print job
esc.stopPrintJob()
// 6. Send commands
bleHelper?.writeCommands(esc.commands)
}
// Wake the printer
esc.wake()
// Enable the printer
esc.enable()
// Print an image
esc.image(image, compress: false, mode: .normal)
// Position the paper
esc.position()
// End the print job
esc.stopPrintJob()
// Set shutdown timeout (Units: Minutes, 0 Disables shutdown)
esc.shutTime(10)
// Set density
esc.thickness(.medium) // .low, .medium, .high
// Set paper type
esc.paperType(.continuous) // .blackMark, .continuous, .gap, .hole
// Query printer information
esc.printerInfo()
// Query printer status
esc.state()
// Query battery level
esc.batteryVol()
// Query Bluetooth name
esc.btName()
// Query firmware version
esc.printerVersion()
// Query MAC Address
esc.mac()
// Query SN Number
esc.sn()
// Query printer model
esc.printerModel()
// Send commands
bleHelper?.writeCommands(esc.commands)
// Set a callback for printer response data
escCommand?.read = { [weak self] data, error in
if let data = data {
print("Printer response: \(data)")
// Parse query results or status information
}
}

TSPL commands are used by label and barcode printers. See the TSPL command reference for details.

private var tspl: BasicTSPL?
func setupTSPL() {
tspl = BasicTSPL()
tspl?.basicTSPL(lifecycle, TSPLPrinter_GENERIC)
// Set callbacks
tspl?.read = { [weak self] data, error in
if let data = data {
print("Printer response: \(data)")
}
}
tspl?.bleDidConnectPeripheral = { peripheral in
print("Connected: \(peripheral.name ?? "")")
}
tspl?.bleDidDisconnectPeripheral = { peripheral, error in
print("Disconnected: \(error?.localizedDescription ?? "")")
}
}
func printLabel() {
guard let tspl = tspl else { return }
// Page setup
let page = TPage().width(60).height(40)
let direction = TDirection().direction(.up_out).mirror(.no_mirror)
// Text
let title = TText()
.x(180).y(30)
.font(.TSS24)
.xmulti(2).ymulti(2)
.content("商品标签")
// Barcode
let barcode = TBarcode()
.x(100).y(200)
.type("128")
.height(60)
.content("6901234567890")
// QR code
let qrcode = TQRCode()
.x(350).y(100)
.cellWidth(4)
.content("https://example.com")
// Execute print
tspl.page(page)
.direction(direction)
.gap(true)
.cls()
.text(title)
.barcode(barcode)
.qrcode(qrcode)
.print(1)
}

CPCL commands are used by portable label printers. See the CPCL command reference for details.

private var cpcl: BasicCPCL?
func setupCPCL() {
cpcl = BasicCPCL()
cpcl?.basicCPCL(lifecycle)
}
func printCPCLLabel() {
guard let cpcl = cpcl else { return }
// Page setup
let page = CPCLPage().width(576).height(400)
// Text
let title = CPCLText()
.x(50).y(50)
.content("商品标签")
// Barcode
let barcode = CPCLBarcode()
.x(50).y(150)
.content("1234567890")
// Execute print
cpcl.page(page)
.text(title)
.barcode(barcode)
.print()
}
import CoreBluetooth
class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
private var centralManager: CBCentralManager!
private var discoveredPeripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func startScan() {
if centralManager.state == .poweredOn {
centralManager.scanForPeripherals(withServices: nil, options: nil)
}
}
func stopScan() {
centralManager.stopScan()
}
func connect(_ peripheral: CBPeripheral) {
centralManager.connect(peripheral, options: nil)
}
// MARK: - CBCentralManagerDelegate
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("Bluetooth enabled")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,
advertisementData: [String: Any], rssi RSSI: NSNumber) {
if !discoveredPeripherals.contains(peripheral) {
discoveredPeripherals.append(peripheral)
print("Device found: \(peripheral.name ?? "Unknown")")
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected: \(peripheral.name ?? "")")
peripheral.delegate = self
peripheral.discoverServices(nil)
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?) {
print("Disconnected: \(error?.localizedDescription ?? "")")
}
}

Add the following to Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>Bluetooth permission is required to connect to the printer</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>Bluetooth permission is required to connect to the printer</string>
  • Native Swift Package
  • Complete Swift API
  • async/await support
  • SwiftUI integration examples
  • Combine support
  • Improved macOS support

For complete examples, see:

Follow our GitHub for updates.

If you have suggestions or requirements for the Swift SDK, please open an issue.