# iOS

> **Library 2.0.0.213** · SAE J2534 v04.04 API

## Artifact

`libj2534.xcframework` — static library, minimum iOS 12.0.

| Slice | Architectures |
|-------|---------------|
| `ios-arm64` | device |
| `ios-arm64_x86_64-simulator` | simulator (Apple Silicon + Intel) |

Each slice carries the public headers (`j2534.h`, `j2534_ota.h`), a module
map (Swift module `J2534`) and a privacy manifest (`PrivacyInfo.xcprivacy`).
mbedTLS is compiled in — the framework has no external dependencies beyond
system frameworks.

The bare `libj2534_v04_04.a` next to the XCFramework is a device-only
archive for gomobile builds; application developers should use the
XCFramework.

## Xcode setup

1. Drag `libj2534.xcframework` into *General → Frameworks, Libraries, and
   Embedded Content*. Set *Embed* to **Do Not Embed** (the library is
   static).
2. Add `-lc++` to *Build Settings → Other Linker Flags*. The library is C++
   behind a C API; a pure Swift or ObjC target does not link the C++ runtime
   by itself.
3. Nothing else. `CoreBluetooth.framework` autolinks through the module map;
   networking uses BSD sockets.

Import:

```swift
import J2534          // Swift
```

```objc
@import J2534;        // Objective-C
// or: #include "j2534.h"
```

## Info.plist keys your app must provide

| Key | When | Note |
|-----|------|------|
| `NSBluetoothAlwaysUsageDescription` | BLE connections (`u:`, `b:`) | iOS shows the permission prompt on first CoreBluetooth use |
| `NSLocalNetworkUsageDescription` | LAN/Wi-Fi connections (`n:`) | iOS 14+ shows the local-network prompt on first TCP connect to the adapter |

Without the matching key iOS terminates the app on first use of the
transport.

## Connection strings

Same format as the other platforms (see
[GETTING_STARTED.md](GETTING_STARTED.md)):

- `ScanDoc;n:192.168.1.100` — LAN/Wi-Fi (TCP)
- `ScanDoc;u:<CoreBluetooth UUID>` — BLE by peripheral UUID
- `ScanDoc;b:N4999` — BLE by advertised name prefix

There is no USB path on iOS: the `serial_*` transport is excluded from the
iOS build entirely.

## Swift notes

- Protocol and IOCTL IDs are C macros with casts (`(pt_prot_id_t)5U`) and do
  not import into Swift. Use the numeric values from
  [API_REFERENCE.md](API_REFERENCE.md), e.g. `let CAN: UInt32 = 5`,
  `let ISO15765: UInt32 = 6`.
- `PassThruOpen` takes a mutable `char *`; pass a copy
  (`strdup`/`Array<CChar>`), not a Swift string literal.
- See [`examples/ios`](../../examples/ios/) for a runnable SwiftUI example
  covering BLE and Wi-Fi.

## Configuration and logs

`j2534.json` and `.qlog` logs live in the app sandbox:
`<app container>/Library/Application Support/Quantex/`. File format and
behavior match the other platforms — see
[CONFIGURATION.md](CONFIGURATION.md) and [LOG_FORMAT.md](LOG_FORMAT.md).

To ship with logging off, write `j2534.json` before the first
`PassThruOpen`. At `log_level: -1` no `.qlog` file is created and no message
payload is written anywhere:

```swift
let dir = FileManager.default
    .urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
    .appendingPathComponent("Quantex", isDirectory: true)
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
try #"{"log_level": -1, "devices": []}"#
    .write(to: dir.appendingPathComponent("j2534.json"),
           atomically: true, encoding: .utf8)
```

The file lives inside the app container, so nothing outside the app can turn
logging back on. For a support case ship the same file with `"log_level": 3`.
An empty `devices` array is fine as long as you open the device with an
explicit connection string; `PassThruOpen(NULL)` needs a device entry.

## Privacy manifest and App Store

The bundled `PrivacyInfo.xcprivacy` declares: no tracking, no collected data
types, and one accessed-API category — file timestamps (reason `C617.1`,
log rotation inside the app container). Xcode 15+ aggregates it into the
app's privacy report automatically; no extra work is needed for App Store
submission.

## Firmware update

`OtaUpdate` / `OtaAbort` from `j2534_ota.h` work over BLE and Wi-Fi — see
[FIRMWARE_UPDATE.md](FIRMWARE_UPDATE.md).
