Вот некоторые подробности о моей реализации:
- Регистрация AID: я зарегистрировал правильный AID для значка Vigik в файле прав и правильный тег тип опрашивается с использованием NFCTagReaderSession.
- Обнаружены другие карты: карты NFC, такие как ISO 14443 и MIFARE, обнаруживаются и считываются правильно.
// ViewController.swift
// testNFCCOre
//
// Created by mind on 12/11/24.
//
import UIKit
import CoreNFC
class ViewController: UIViewController, NFCTagReaderSessionDelegate {
var nfcSession: NFCReaderSession?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func onTapScan(_ sender: Any) {
startScanning()
}
func startScanning() {
guard NFCTagReaderSession.readingAvailable else {
print("NFC is not supported on this device.")
return
}
// Create a session for raw tag reading
nfcSession = NFCTagReaderSession(pollingOption: [.iso14443,.iso18092,.iso15693], delegate: self, queue: DispatchQueue.main)
// Begin the session
nfcSession?.begin()
}
// Called when the session becomes active
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
print("NFC session is active.")
// You can inform the user that the NFC reader is active or show a message
}
// Called when the session is invalidated (e.g., user cancels or an error occurs)
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
if let error = error as? NFCReaderError {
switch error.code {
case .readerSessionInvalidationErrorUserCanceled:
print("User canceled the session.")
case .readerSessionInvalidationErrorSessionTimeout:
print("Session timed out.")
case .readerSessionInvalidationErrorSystemIsBusy:
print("System is busy. Please try again.")
default:
print("Session invalidated with error: \(error.localizedDescription)")
}
} else {
print("Session invalidated with error: \(error.localizedDescription)")
}
}
// Called when the session detects NFC tags
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
let tag = tags.first!
session.connect(to: tag) { error in
if let error = error {
print("Connection failed: \(error.localizedDescription)")
return
}
print("Tag connected successfully!")
// Continue processing the tag depending on its type
for tag in tags {
switch tag {
case .miFare(let mifareTag):
print("MIFARE tag detected: \(mifareTag)")
self.handleMifareTag(mifareTag)
case .feliCa(let feliCaTag):
print("FeliCa tag detected: \(feliCaTag)")
self.handleFeliCaTag(feliCaTag)
case .iso7816(let iso7816Tag):
print("ISO 7816 tag detected: \(iso7816Tag)")
let aidData = Data([
0xA0, 0x00, 0x00, 0x00, 0x86, 0x32, 0x05, 0x49,
0x47, 0x49, 0x4B, 0xAE, 0x5F, 0x33
])
// Create APDU SELECT command
let command = NFCISO7816APDU(
instructionClass: 0x00,
instructionCode: 0xA4,
p1Parameter: 0x04,
p2Parameter: 0x00,
data: aidData,
expectedResponseLength: -1
)
// Send the APDU command
iso7816Tag.sendCommand(apdu: command) { response, sw1, sw2, error in
if let error = error {
print("Error sending APDU: \(error.localizedDescription)")
return
}
// Parse the response
print("Response: \(response)")
print("Status words: SW1=\(sw1), SW2=\(sw2)")
// Process specific application template if needed
if sw1 == 0x90 && sw2 == 0x00 {
print("Application selected successfully!")
} else {
print("Application selection failed with status words \(sw1), \(sw2)")
}
}
self.handleIso7816Tag(iso7816Tag)
case .iso15693(let nfcATag):
print("ISO 15693 tag detected: \(nfcATag)")
self.handleNfcATag(nfcATag)
default:
print("Unknown tag type detected.")
}
}
session.invalidate()
}
}
// Handle MIFARE tag
func handleMifareTag(_ mifareTag: NFCMiFareTag) {
// Process MIFARE tag data
print("MIFARE UID: \(mifareTag.identifier)")
}
// Handle FeliCa tag
func handleFeliCaTag(_ feliCaTag: NFCFeliCaTag) {
// Print available information from NFCFeliCaTag
print("FeliCa tag detected.")
}
// Handle ISO 7816 tag (smart cards)
func handleIso7816Tag(_ iso7816Tag: NFCISO7816Tag) {
// Process ISO 7816 tag data
print("Tag Identifier: \(iso7816Tag.identifier.hexString())")
let hexString = "4a6f686e" // Hex for "John"
if let decodedText = hexStringToText(hexString: iso7816Tag.identifier.hexString()) {
print("Decoded text: \(decodedText)") // Outputs: John
}
print("Application Data: \(String(describing: iso7816Tag.applicationData))")
print("Historical Bytes: \(String(describing: iso7816Tag.historicalBytes))")
if let historicalBytes = iso7816Tag.historicalBytes {
let hexString = historicalBytes.map { String(format: "%02hhx", $0) }.joined()
print("Historical Bytes as Hex: \(hexString)")
}
print("Selected AID: \(iso7816Tag.initialSelectedAID)")
}
// Handle NFC-A tag
func handleNfcATag(_ nfcATag: NFCISO15693Tag) {
// Process NFC-A tag data
print("NFC-A UID: \(nfcATag.identifier)")
}
// Convert Hex String to Text
func hexStringToText(hexString: String) -> String? {
var hex = hexString
var data = Data()
while hex.count > 0 {
let c = hex.prefix(2)
hex = String(hex.dropFirst(2))
if let byte = UInt8(c, radix: 16) {
data.append(byte)
}
}
return String(data: data, encoding: .utf8)
}
}
// Convert Data to Hex String
extension Data {
func hexString() -> String {
return self.map { String(format: "%02hhx", $0) }.joined()
}
func hexStringToData(hexString: String) -> Data? {
var data = Data()
// Ensure the hex string is in valid form (even length)
let cleanedHexString = hexString.replacingOccurrences(of: " ", with: "").uppercased()
// Process every pair of characters (each byte)
var startIndex = cleanedHexString.startIndex
while startIndex < cleanedHexString.endIndex {
let endIndex = cleanedHexString.index(startIndex, offsetBy: 2)
let hexPair = String(cleanedHexString[startIndex..
Подробнее здесь: https://stackoverflow.com/questions/791 ... g-core-nfc