Skip to content
Mobile
Skill

/core-nfc

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.

From plugin
swift-ios-skills
1.3k86 skills1 MCP

Claude Code

$ npx -y skills add dpearson2699/swift-ios-skills --skill core-nfc --agent claude-code

SKILL.md

core-nfc.SKILL.md
name: core-nfc
description: "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."

CoreNFC

Read and write NFC tags on iPhone using the CoreNFC framework. Covers NDEF reader sessions, tag reader sessions, NDEF message construction, entitlements, and background tag reading.

Contents

  • [Setup](#setup)
  • [NDEF Reader Session](#ndef-reader-session)
  • [Tag Reader Session](#tag-reader-session)
  • [Writing NDEF Messages](#writing-ndef-messages)
  • [NDEF Payload Types](#ndef-payload-types)
  • [Background Tag Reading](#background-tag-reading)
  • [Common Mistakes](#common-mistakes)
  • [Review Checklist](#review-checklist)
  • [References](#references)

Setup

Project Configuration

1. Add the **Near Field Communication Tag Reading** capability in Xcode 2. Add `NFCReaderUsageDescription` to Info.plist with a user-facing reason string 3. Add the `com.apple.developer.nfc.readersession.formats` entitlement with the current `TAG` value; do not add legacy `NDEF` 4. For ISO 7816 tags, add supported application identifiers to `com.apple.developer.nfc.readersession.iso7816.select-identifiers` in Info.plist 5. For FeliCa tags, add supported system codes to `com.apple.developer.nfc.readersession.felica.systemcodes`; do not use wildcard system codes

Device Requirements

NFC reading requires iPhone 7 or later. Always check for reader session availability before creating NFC UI or sessions. Use the concrete reader session type you are about to create.

import CoreNFC

guard NFCNDEFReaderSession.readingAvailable else {
    // Device does not support NFC or feature is restricted
    showUnsupportedMessage()
    return
}

Key Types

| Type | Role | |---|---| | `NFCNDEFReaderSession` | Scans for NDEF-formatted tags | | `NFCTagReaderSession` | Scans for ISO7816, ISO15693, FeliCa, MIFARE tags | | `NFCNDEFMessage` | Collection of NDEF payload records | | `NFCNDEFPayload` | Single record within an NDEF message | | `NFCNDEFTag` | Protocol for interacting with an NDEF-capable tag |

NDEF Reader Session

Use `NFCNDEFReaderSession` to read NDEF-formatted data from tags. This is the simplest path for reading standard tag content like URLs, text, and MIME data.

import CoreNFC

final class NDEFReader: NSObject, NFCNDEFReaderSessionDelegate {
    private var session: NFCNDEFReaderSession?

    func beginScanning() {
        guard NFCNDEFReaderSession.readingAvailable else { return }

        session = NFCNDEFReaderSession(
            delegate: self,
            queue: nil,
            invalidateAfterFirstRead: false
        )
        session?.alertMessage = "Hold your iPhone near an NFC tag."
        session?.begin()
    }

    // MARK: - NFCNDEFReaderSessionDelegate

    func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) {
        // Session is scanning
    }

    func readerSession(
        _ session: NFCNDEFReaderSession,
        didDetectNDEFs messages: [NFCNDEFMessage]
    ) {
        for message in messages {
            for record in message.records {
                processRecord(record)
            }
        }
    }

    func readerSession(
        _ session: NFCNDEFReaderSession,
        didInvalidateWithError error: Error
    ) {
        let nfcError = error as? NFCReaderError
        if nfcError?.code != .readerSessionInvalidationErrorFirstNDEFTagRead,
           nfcError?.code != .readerSessionInvalidationErrorUserCanceled {
            print("Session invalidated: \(error.localizedDescription)")
        }
        self.session = nil
    }
}

Reading with Tag Connection

For read-write operations, use the tag-detection delegate method to connect to individual tags:

func readerSession(
    _ session: NFCNDEFReaderSession,
    didDetect tags: [any NFCNDEFTag]
) {
    guard let tag = tags.first else {
        session.restartPolling()
        return
    }

    session.connect(to: tag) { error in
        if let error {
            session.invalidate(errorMessage: "Connection failed: \(error)")
            return
        }

        tag.queryNDEFStatus { status, capacity, error in
            guard error == nil else {
                session.invalidate(errorMessage: "Query failed.")
                return
            }

            switch status {
            case .notSupported:
                session.invalidate(errorMessage: "Tag is not NDEF compliant.")
            case .readOnly:
                tag.readNDEF { message, error in
                    if let message {
                        self.processMessage(message)
                    }
                    session.invalidate()
                }
            case .readWrite:
                tag.readNDEF { message, error in
                    if let message {
                        self.processMessage(message)
                    }
                    session.alertMessage = "Tag read successfully."
                    session.invalidate()
                }
            @unknown default:
                session.invalidate()
            }
        }
    }
}

Tag Reader Session

Use `NFCTagReaderSession` when you need direct access to the native tag protocol (ISO 7816, ISO 15693, FeliCa, or MIFARE).

| Polling option | Tags | |---|---| | `.iso14443` | ISO 7816-compatible and MIFARE | | `.iso15693` | ISO 15693 | | `.iso18092` | FeliCa |

Do not use this session for payment-related AIDs. Load [nfc-patterns.md](references/nfc-patterns.md) for protocol-specific connection, APDU, command, and response handling.

Writing NDEF Messages

Write NDEF data to a connected tag. Always check `readWrite` status first.

func writeToTag(
    tag: any NFCNDEFTag,
    session: NFCNDEFReaderSession,
    url: URL
) {
    tag.queryNDEFStatus { status, capacity, error in
        guard status == .read
Read more
@dpearson2699
Ships withswift-ios-skills

86 agent skills optimized for iOS 26+ development with Swift 6.3 and modern Apple frameworks.

1.3k86 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.3k
Star history of dpearson2699/swift-ios-skills on GitHub, a chart by star-history.com

Other skills on swift-ios-skills.

alarmkit

alarmkit

Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple…

app-clips

app-clips

Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store…

More skills from other plugins.

deep-code-review

deep-code-review

In-depth design-focused code review - understands codebase context before evaluating PR changes, posts structured feedback to…

expo1d53k
@expo@expoInstall Skill
modlens

modlens

Plug-in vision for text-only models. Hard rule: when a file path or URL with an image extension (.png, .jpg, .jpeg, .webp, .gif,…

modlens2w4.6k
@liustack@liustackInstall Skill
appllama-app-design-skill

appllama-app-design-sk…

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile…

appllama2mo3.9k
@appllama@appllamaInstall Skill

Questions about core-nfc.

Which coding agents can use core-nfc?
core-nfc installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.