6#include "ios/qiosnfcndefsessiondelegate_p.h"
7#include "ios/qiostagreaderdelegate_p.h"
8#include "ios/qiosndefnotifier_p.h"
16#import <CoreNFC/NFCReaderSession.h>
17#import <CoreNFC/NFCNDEFReaderSession.h>
18#import <CoreNFC/NFCTagReaderSession.h>
22QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl()
24 auto notifier = std::make_unique<QNfcNdefNotifier>();
26 if (@available(iOS 13, *))
27 delegate = [[QT_MANGLE_NAMESPACE(QIosTagReaderDelegate) alloc] initWithListener:
this];
29 connect(
this, &QNearFieldManagerPrivateImpl::tagDiscovered,
30 this, &QNearFieldManagerPrivateImpl::onTagDiscovered,
31 Qt::QueuedConnection);
32 connect(
this, &QNearFieldManagerPrivateImpl::didInvalidateWithError,
33 this, &QNearFieldManagerPrivateImpl::onDidInvalidateWithError,
34 Qt::QueuedConnection);
36 ndefDelegate = [[QIosNfcNdefSessionDelegate alloc] initWithNotifier:notifier.get()];
38 auto watchDog = notifier.release();
40 connect(watchDog, &QNfcNdefNotifier::tagDetected,
41 this, &QNearFieldManagerPrivateImpl::onTagDiscovered,
42 Qt::QueuedConnection);
43 connect(watchDog, &QNfcNdefNotifier::invalidateWithError,
44 this, &QNearFieldManagerPrivateImpl::onDidInvalidateWithError,
45 Qt::QueuedConnection);
47 qCWarning(QT_IOS_NFC,
"Failed to allocate NDEF reading session's delegate");
50 sessionTimer.setInterval(2000);
51 sessionTimer.setSingleShot(
true);
52 connect(&sessionTimer, &QTimer::timeout,
this, &QNearFieldManagerPrivateImpl::onSessionTimer);
57 if (@available(iOS 13, *))
63 if (
auto queue = qt_Nfc_Queue()) {
64 dispatch_sync(queue, ^{
69 [ndefDelegate release];
74 switch (accessMethod) {
75 case QNearFieldTarget::AnyAccess:
76 case QNearFieldTarget::NdefAccess:
77 return NFCNDEFReaderSession.readingAvailable;
78 case QNearFieldTarget::TagTypeSpecificAccess:
79 if (@available(iOS 13, *))
80 return NFCTagReaderSession.readingAvailable;
82 case QNearFieldTarget::UnknownAccess:
92 activeAccessMethod = QNearFieldTarget::UnknownAccess;
94 switch (accessMethod) {
95 case QNearFieldTarget::UnknownAccess:
96 case QNearFieldTarget::AnyAccess:
98 case QNearFieldTarget::TagTypeSpecificAccess:
99 if (@available(iOS 13, *))
100 if (NFCTagReaderSession.readingAvailable) {
101 detectionRunning = scheduleSession(accessMethod);
102 if (detectionRunning)
103 activeAccessMethod = accessMethod;
104 return detectionRunning;
107 case QNearFieldTarget::NdefAccess:
108 if (NFCNDEFReaderSession.readingAvailable) {
109 detectionRunning = scheduleSession(accessMethod);
110 if (detectionRunning)
111 activeAccessMethod = accessMethod;
112 return detectionRunning;
122 if (!detectionRunning)
125 isSessionScheduled =
false;
127 if (activeAccessMethod == QNearFieldTarget::TagTypeSpecificAccess) {
128 stopSession(errorMessage);
129 }
else if (activeAccessMethod == QNearFieldTarget::NdefAccess) {
130 stopNdefSession(errorMessage);
132 qCWarning(QT_IOS_NFC,
"Unknown access method, cannot stop target detection");
136 detectionRunning =
false;
137 Q_EMIT targetDetectionStopped();
142 if (sessionTimer.isActive()) {
143 isSessionScheduled =
true;
146 isSessionScheduled =
false;
148 if (accessMethod == QNearFieldTarget::TagTypeSpecificAccess) {
151 }
else if (accessMethod == QNearFieldTarget::NdefAccess) {
152 return startNdefSession();
160 if (@available(iOS 13, *)) {
161 [delegate startSession];
170 if (
auto queue = qt_Nfc_Queue()) {
171 __block
bool startSessionSucceded =
false;
172 dispatch_sync(queue, ^{ startSessionSucceded = [ndefDelegate startSession]; });
173 return startSessionSucceded;
181 Q_ASSERT(activeAccessMethod == QNearFieldTarget::TagTypeSpecificAccess);
185 if (@available(iOS 13, *)) {
186 [delegate stopSession:error];
192 Q_ASSERT(activeAccessMethod == QNearFieldTarget::NdefAccess);
196 if (
auto queue = qt_Nfc_Queue()) {
197 dispatch_sync(queue, ^{
198 [ndefDelegate stopSession:error];
205 auto i = detectedTargets.begin();
206 while (i != detectedTargets.end()) {
210 qCWarning(QT_IOS_NFC,
"Stale private near field target found");
211 i = detectedTargets.erase(i);
218 if (activeAccessMethod != QNearFieldTarget::NdefAccess)
219 [delegate alertMessage:message];
221 if (detectionRunning) {
223 qCWarning(QT_IOS_NFC,
224 "User information must be set prior before the target detection started");
228 if (
auto queue = qt_Nfc_Queue()) {
229 dispatch_sync(queue, ^{
230 [ndefDelegate setAlertMessage:message];
238 if (activeAccessMethod == QNearFieldTarget::NdefAccess) {
240 target =
new QNearFieldTargetPrivateImpl(ndefDelegate, tag);
242 target =
new QNearFieldTargetPrivateImpl(tag);
245 detectedTargets += target;
247 connect(target, &QNearFieldTargetPrivateImpl::targetLost,
248 this, &QNearFieldManagerPrivateImpl::onTargetLost);
249 Q_EMIT targetDetected(
new QNearFieldTarget(target,
this));
254 detectedTargets.removeOne(target);
255 Q_EMIT targetLost(target->q_ptr);
257 if (detectionRunning && detectedTargets.isEmpty())
258 onDidInvalidateWithError(
true);
264 sessionTimer.start();
266 if (detectionRunning && doRestart && scheduleSession(activeAccessMethod))
269 detectionRunning =
false;
270 Q_EMIT targetDetectionStopped();
275 if (isSessionScheduled && !scheduleSession(activeAccessMethod)) {
276 detectionRunning =
false;
277 Q_EMIT targetDetectionStopped();
bool isSupported(QNearFieldTarget::AccessMethod accessMethod) const override
bool startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) override
~QNearFieldManagerPrivateImpl()