Hi, does anyone know how to enable creating or configuring Near NFC Reader in SwiftUI?
I've already added the capability, the permissions in info.plist, the entitlement, and the SwiftUI code, but without success. Here's the example code:
class PaymentT2PViewModel: NSObject, ObservableObject {
@Published var paymentT2PUIState: PaymentT2PUIState
// MARK: - NFC Properties
@Published var nfcMessage: String = .empty
@Published var isNFCReading: Bool = false
private var nfcSession: NFCTagReaderSession?
init(paymentT2PUIState: PaymentT2PUIState) {
self.paymentT2PUIState = paymentT2PUIState
super.init()
)
}
func startNFCReading() {
print("INICIO: startNFCReading llamado")
guard NFCTagReaderSession.readingAvailable else {
print("ERROR: NFC NO disponible en este dispositivo")
Task { @MainActor in
self.nfcMessage = "NFC no disponible en este dispositivo"
}
return
}
print("NFC disponible, creando sesión...")
nfcSession = NFCTagReaderSession(
pollingOption: [.iso14443, .iso15693, .iso18092],
delegate: self,
queue: nil
)
print("Sesión creada, configurando mensaje...")
nfcSession?.alertMessage = "Acerca la tarjeta al iPhone"
nfcSession?.begin()
print("Sesión NFC INICIADA - debería aparecer popup")
Task { @MainActor in
self.isNFCReading = true
}
}
func stopNFCReading() {
nfcSession?.invalidate()
Task { @MainActor in
self.isNFCReading = false
}
}
extension PaymentT2PViewModel: NFCTagReaderSessionDelegate {
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
print("SESIÓN INVALIDADA")
print("Error: (error.localizedDescription)")
if let readerError = error as? NFCReaderError {
print("Código de error: \(readerError.code.rawValue)")
print("¿Es cancelación del usuario?: \(readerError.code == .readerSessionInvalidationErrorUserCanceled)")
}
Task { @MainActor in
if let readerError = error as? NFCReaderError {
if readerError.code != .readerSessionInvalidationErrorUserCanceled {
self.nfcMessage = "Error: \(readerError.localizedDescription)"
}
}
self.isNFCReading = false
}
}
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
print("NFC Session activa")
}
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
guard let firstTag = tags.first else { return }
session.connect(to: firstTag) { [weak self] error in
if let error = error {
session.invalidate(errorMessage: "Error al conectar: \(error.localizedDescription)")
return
}
Task { @MainActor [weak self] in
await self?.handleTag(firstTag, session: session)
}
}
}
private func handleTag(_ tag: NFCTag, session: NFCTagReaderSession) async {
switch tag {
case .iso7816(let tag):
await handleISO7816Tag(tag, session: session)
case .miFare(let tag):
await handleMiFareTag(tag, session: session)
case .iso15693(let tag):
await handleISO15693Tag(tag, session: session)
case .feliCa(let tag):
await handleFeliCaTag(tag, session: session)
@unknown default:
session.invalidate(errorMessage: "Tipo de tag no soportado")
}
}
private func handleISO7816Tag(_ tag: NFCISO7816Tag, session: NFCTagReaderSession) async {
let uid = tag.identifier.map { String(format: "%02X", $0) }.joined()
nfcMessage = """
ISO7816 Tag detectado
UID: \(uid)
Historical Bytes: \(tag.historicalBytes?.map { String(format: "%02X", $0) }.joined() ?? "N/A")
"""
session.alertMessage = "Tag leído exitosamente"
session.invalidate()
}
private func handleMiFareTag(_ tag: NFCMiFareTag, session: NFCTagReaderSession) async {
let uid = tag.identifier.map { String(format: "%02X", $0) }.joined()
nfcMessage = """
MiFare Tag detectado
UID: \(uid)
Tipo: \(tag.mifareFamily.description)
"""
session.alertMessage = "Tag leído exitosamente"
session.invalidate()
}
private func handleISO15693Tag(_ tag: NFCISO15693Tag, session: NFCTagReaderSession) async {
let uid = tag.identifier.map { String(format: "%02X", $0) }.joined()
nfcMessage = """
ISO15693 Tag detectado
UID: \(uid)
IC Manufacturer: \(tag.icManufacturerCode)
"""
session.alertMessage = "Tag leído exitosamente"
session.invalidate()
}
private func handleFeliCaTag(_ tag: NFCFeliCaTag, session: NFCTagReaderSession) async {
let idm = tag.currentIDm.map { String(format: "%02X", $0) }.joined()
let pmm = tag.currentSystemCode.map { String(format: "%02X", $0) }.joined()
nfcMessage = """
FeliCa Tag detectado
IDm: \(idm)
System Code: \(pmm)
"""
session.alertMessage = "Tag leído exitosamente"
session.invalidate()
}
}
// MARK: - Helper Extension
extension NFCMiFareFamily {
var description: String {
switch self {
case .unknown: return "Desconocido"
case .ultralight: return "Ultralight"
case .plus: return "Plus"
case .desfire: return "DESFire"
@unknown default: return "Otro"
}
}
}
struct PaymentT2PView: View {
@ObservedObject var paymentT2PViewModel: PaymentT2PViewModel
var body: some View {
ZStack {
if paymentT2PViewModel.paymentT2PUIState.showingResult {
print("Navigate")
} else {
print("False")
}
}
.onAppear {
paymentT2PViewModel.startNFCReading()
}
.onDisappear {
paymentT2PViewModel.stopNFCReading()
}
}}
However, I'm getting code error messages, and I'm testing this on an iPhone 11.
What am I doing wrong?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Colombia is not yet listed as a Tap to Pay user, but it is in the process of becoming so.
We are currently a group of developers at a company in Colombia working on a project to integrate Tap to Pay into our application. After reviewing Apple's documentation, my company is not certified to meet Apple's security requirements, PCI standards, or licensing requirements. However, the payment service provider we have contracted for this is in the process of obtaining the certifications, authorizations, and licenses that Apple specifies. Our team members and managers overseeing this Tap to Pay project have told us that we, as iOS developers, should integrate and use the Proximity Reader API, but we know that we, as developers, are not authorized by Apple to do so.
Is the payment service provider the only one who can make this possible, enabling its use with NFC and Proximity Reader?
I would like to know if the service provider will provide us with the SDK containing the Proximity Reader API for integration into the project, or if my company will have to implement the Proximity Reader API ourselves?