SwiftNFC.swift (5344B)
1 // MIT License 2 // Copyright © Ming 3 // https://github.com/1998code/SwiftNFC 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 // and associated documentation files (the "Software"), to deal in the Software without restriction, 7 // including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in all copies or 12 // substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 // 20 /** 21 * @author Marc Stibane 22 */ 23 import SwiftUI 24 import CoreNFC 25 26 @available(iOS 15.0, *) 27 public class NFCWriter: NSObject, ObservableObject, NFCNDEFReaderSessionDelegate { 28 29 public var startAlert = String(localized: "Hold your iPhone near the tag.") 30 public var endAlert = EMPTYSTRING 31 public var msg = EMPTYSTRING 32 public var type = "T" // T=Text - U=URL 33 public var data: Data? = nil 34 35 public var session: NFCNDEFReaderSession? 36 37 public func write(_ data: Data? = nil) { 38 guard NFCNDEFReaderSession.readingAvailable else { 39 print("Error readingAvailable") 40 return 41 } 42 self.data = data 43 session = NFCNDEFReaderSession(delegate: self, queue: nil, invalidateAfterFirstRead: false) 44 if let session { 45 session.alertMessage = self.startAlert 46 session.begin() 47 } else { 48 print("Error NFCNDEFReaderSession") 49 } 50 } 51 52 public func readerSession(_ session: NFCNDEFReaderSession, didDetectNDEFs messages: [NFCNDEFMessage]) { 53 print("didDetectNDEFs", messages) 54 } 55 56 public func readerSession(_ session: NFCNDEFReaderSession, didDetect tags: [NFCNDEFTag]) { 57 if tags.count > 1 { 58 let retryInterval = DispatchTimeInterval.milliseconds(500) 59 session.alertMessage = "Detected more than 1 tag. Please try again." 60 DispatchQueue.global().asyncAfter(deadline: .now() + retryInterval, execute: { 61 session.restartPolling() 62 }) 63 return 64 } 65 66 let tag = tags.first! 67 session.connect(to: tag, completionHandler: { (error: Error?) in 68 if nil != error { 69 session.alertMessage = "Unable to connect to tag." 70 session.invalidate() 71 return 72 } 73 74 tag.queryNDEFStatus(completionHandler: { (ndefStatus: NFCNDEFStatus, capacity: Int, error: Error?) in 75 guard error == nil else { 76 session.alertMessage = "Unable to query the status of the tag." 77 session.invalidate() 78 return 79 } 80 81 switch ndefStatus { 82 case .notSupported: 83 session.alertMessage = "Tag is not NDEF compliant." 84 session.invalidate() 85 case .readOnly: 86 session.alertMessage = "Read only tag detected." 87 session.invalidate() 88 case .readWrite: 89 let payload: NFCNDEFPayload? 90 if self.type == "T" { 91 payload = NFCNDEFPayload.init( 92 format: .nfcWellKnown, 93 type: Data("\(self.type)".utf8), 94 identifier: Data(), 95 payload: self.data ?? Data("\(self.msg)".utf8) 96 ) 97 } else { 98 payload = NFCNDEFPayload.wellKnownTypeURIPayload(string: "\(self.msg)") 99 } 100 let message = NFCNDEFMessage(records: [payload].compactMap({ $0 })) 101 tag.writeNDEF(message, completionHandler: { (error: Error?) in 102 if nil != error { 103 session.alertMessage = "Write to tag failed: \(error!)" 104 } else { 105 session.alertMessage = self.endAlert != EMPTYSTRING ? self.endAlert 106 : "Write \(self.msg) to tag successful." 107 } 108 session.invalidate() 109 }) 110 @unknown default: 111 session.alertMessage = "Unknown tag status." 112 session.invalidate() 113 } 114 }) 115 }) 116 } 117 118 public func readerSessionDidBecomeActive(_ session: NFCNDEFReaderSession) { 119 } 120 121 public func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) { 122 print("Session did invalidate with error: \(error)") 123 self.session = nil 124 } 125 }