Read and write NFC tags using CoreNFC. Use when scanning NDEF tags, reading ISO7816/ISO15693/FeliCa/MIFARE tags, writing NDEF messages, handling NFC session lifecycle, configuring NFC entitlements, or implementing background tag reading in iOS apps.
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Read and write NFC tags on iPhone using CoreNFC. Supports NDEF tag reader sessions, native ISO 7816/15693/FeliCa/MIFARE tag communication, and background tag reading.
NFCReaderUsageDescription to Info.plist.com.apple.developer.nfc.readersession.formats with array value ["TAG"] (do not use legacy NDEF).com.apple.developer.nfc.readersession.iso7816.select-identifiers.com.apple.developer.nfc.readersession.felica.systemcodes (no wildcards).Always verify NFCNDEFReaderSession.readingAvailable before presenting NFC UI.
Read NDEF tags using NFCNDEFReaderSession:
import CoreNFC
final class NFCReader: NSObject, NFCNDEFReaderSessionDelegate {
var session: NFCNDEFReaderSession?
func beginScan() {
guard NFCNDEFReaderSession.readingAvailable else { return }
session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: true)
session?.alertMessage = "Hold iPhone near NFC tag."
session?.begin()
}
func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) {
for message in messages {
for record in message.records {
// Process payload
}
}
}
func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) {
// Handle session timeout, cancellation, or hardware error
}
}Connect to tags and write NDEF messages using NFCTagReaderSession:
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
guard let tag = tags.first else { return }
session.connect(to: tag) { error in
guard error == nil else { session.invalidate(errorMessage: "Connection failed"); return }
guard case let .ndef(ndefTag) = tag else { return }
ndefTag.queryNDEFStatus { status, capacity, error in
guard status == .readWrite else { return }
let payload = NFCNDEFPayload.wellKnownTypeURIPayload(url: URL(string: "https://example.com")!)!
let message = NFCNDEFMessage(records: [payload])
ndefTag.writeNDEF(message) { error in
if error == nil {
session.alertMessage = "Write successful!"
session.invalidate()
}
}
}
}
}Construct standardized NDEF payloads:
// URI Payload
let uriPayload = NFCNDEFPayload.wellKnownTypeURIPayload(url: destinationURL)!
// Text Payload
let textPayload = NFCNDEFPayload.wellKnownTypeTextPayload(string: "Device-101", locale: Locale(identifier: "en"))!
let message = NFCNDEFMessage(records: [uriPayload, textPayload])Supported iPhones continuously scan for NDEF tags containing URL payloads when the screen is on:
.onOpenURL or UIKit scene(_:openURLContexts:).TAG in com.apple.developer.nfc.readersession.formats.session.invalidate() is explicitly called.NFCReaderError.readerSessionInvalidationErrorSessionTimeout.ndefTag.queryNDEFStatus and verify .readWrite status before attempting writes.NFCReaderUsageDescription configured in Info.plistcom.apple.developer.nfc.readersession.formats set to ["TAG"]thienqo/ios-skills
6bf8b62
Canonical home
since May 23, 2026
Also appears in
on Sep 6, 2026
since May 22, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.