The problem I'm facing is that I want to integrate the following frameworks into a SwiftUI project namely: ACSSmartCardIO & SmartCardIO
I'm not proficient with SwiftUI or iOS development to understand how to implement the delegate and use it within SwiftUI.
The docs show: Before connecting Bluetooth card terminals, your app must import ACSSmartCardIO module. You can get an instance of Bluetooth Terminal Manager and Terminal Factory from BluetoothSmartCard.shared object. To receive events from BluetoothTerminalManager object, your app must assign a delegate object to it.
...
import SmartCardIO
import ACSSmartCardIO
...
class ViewController: UIViewController {
...
let manager = BluetoothSmartCard.shared.manager
let factory = BluetoothSmartCard.shared.factory
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
...
// Set the delegate.
manager.delegate = self
...
}
...
}
...
Your app must check the state from CentralManager object and show the message if Bluetooth is not supported or other reasons that your app cannot use Bluetooth on your iOS device.
// MARK: - BluetoothTerminalManagerDelegate
extension ViewController: BluetoothTerminalManagerDelegate {
func bluetoothTerminalManagerDidUpdateState(_ manager: BluetoothTerminalManager) {
var message = ""
switch manager.centralManager.state {
case .unknown, .resetting:
message = "The update is being started. Please wait until Bluetooth is ready."
case .unsupported:
message = "This device does not support Bluetooth low energy."
case .unauthorized:
message = "This app is not authorized to use Bluetooth low energy."
case .poweredOff:
if !firstRun {
message = "You must turn on Bluetooth in Settings in order to use the reader."
}
default:
break
}
if !message.isEmpty {
// TODO: Show the message.
// ...
}
firstRun = false
}
...
}
To find BLE card terminals, you must use BluetoothTerminalManager.startScan(terminalType:) method from your BluetoothTerminalManager object.
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
switch identifier {
case "ScanTerminals":
...
// Start the scan.
manager.startScan(terminalType: .amr220c)
...
default:
break
}
}
}
...
Your code has little to do with UI. SwiftUI only matters when dealing directly with the User Interaction.
An easy way to apply this code to a SwiftUI setup is to put all the code you have in the UIViewController
in a ViewModel that is an ObservableObject
.
Replace
class ViewController: UIViewController {
With
class BluetoothSmartCardViewModel: ObservableObject {
And
extension ViewController: BluetoothTerminalManagerDelegate {
With
extension BluetoothSmartCardViewModel: BluetoothTerminalManagerDelegate {
You will get some errors with any UIKit code such as IBAction
, IBOutlet
, and any viewDid...
methods. You will have to create @Published
variables and func
to compensate for those interacting with a SwiftUI View
vs a Storyboard.
As far as the segue
code, that seems to be the "trickiest" part. There are several ways of handing this.
One way is to have a ScanTerminalsView
and
.onAppear(){
viewModel.manager.startScan(terminalType: .amr220c)
}