taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

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 }