# Reading and Writing Tags

Exchange APDUs with NFC tags through a Socket Mobile NFC reader in PC/SC coupler mode with the iOS CaptureSDK. Covers handling tag arrival and removal with CaptureHelperPcscDelegate, reading a tag with a READ BINARY APDU and writing an NDEF URL record into an NFC Forum Type 2 tag. Includes Swift code samples.

Your application exchanges APDUs with a tag while the NFC reader is in coupler mode, and tag events come through **CaptureHelperPcscDelegate**. See [Modes](/docs/nfc/modes) to switch the reader to coupler mode and set up the delegate.

## Tag arrival and Removal

A tag presented to the coupler arrives through **didNotifyArrivalForTag** and **didNotifyRemovalForTag** is called when the tag leaves the coupler, through **CaptureHelperPcscDelegate**.

The tag is a **CaptureHelperDevice**: keep it to exchange APDUs with it while it is present. The tag UID is still delivered as decoded data from the coupler.

## Swift

```swift
var tag: CaptureHelperDevice?

extension MyViewController: CaptureHelperPcscDelegate {

    func didNotifyArrivalForTag(_ tag: CaptureHelperDevice, withResult result: SKTResult) {
        print("didNotifyArrivalForTag - Result: \(result.rawValue)")
        self.tag = tag
    }

    func didNotifyRemovalForTag(_ tag: CaptureHelperDevice, withResult result: SKTResult) {
        print("didNotifyRemovalForTag - Result: \(result.rawValue)")
        self.tag = nil
    }

}
```

## Reading a tag

Send an APDU to the tag with **transmitDataForTagWithCompletionHandler**. The response holds the tag data followed by the status word `90 00` on success.

On an NFC Forum Type 2 tag (MIFARE Ultralight, NTAG), the PC/SC READ BINARY command returns 16 bytes (4 pages) per call. The user memory, where the NDEF message is stored, starts at page 4:

## Swift

```swift
var tag: CaptureHelperDevice?
let page: UInt8 = 4

tag?.transmitDataForTagWithCompletionHandler(Data([0xFF, 0xB0, 0x00, page, 0x10])) { result, response in
    guard result == .E_NOERROR, let response = response, response.suffix(2) == Data([0x90, 0x00]) else {
        return
    }
    let bytes = response.dropLast(2)
    print("Pages \(page) to \(page + 3): \(bytes.map { String(format: "%02X", $0) }.joined())")
}
```

Read the next pages the same way, from page 8, 12 and so on, until the whole NDEF message is read.

## Writing a URL into a tag

**writeDataForTag** writes bytes into an NFC Forum Type 2 tag, one 4-byte page at a time, starting at the given page. The example writes an NDEF message holding the URL `https://socketmobile.dev`:

## Swift

```swift
var tag: CaptureHelperDevice?

// NDEF TLV with a URI record: 0x04 is the "https://" prefix, followed by "socketmobile.dev", then the terminator TLV
let ndefUrl = Data([
    0x03, 0x15, 0xD1, 0x01, 0x11, 0x55, 0x04,
    0x73, 0x6F, 0x63, 0x6B, 0x65, 0x74, 0x6D, 0x6F, 0x62, 0x69, 0x6C, 0x65,
    0x2E, 0x64, 0x65, 0x76,
    0xFE
])
tag?.writeDataForTag(ndefUrl, startingAtPage: 4) { result, tagResponse in
    print("writeDataForTag - Result: \(result.rawValue)")
}
```

The result is `E_COMMANDDENIED` when the tag refuses a page; `tagResponse` then holds the tag's response.