Post

Replies

Boosts

Views

Activity

Reply to Optional and onTapGesture
Here is the solution. Instead of using onTapGesture, I used a Observable class where I stored all the data from the tag. struct NFCWriteButton : UIViewRepresentable {     @Binding var data: String     @ObservedObject var dataToWrite: NFCData     func updateUIView(_ uiView: UIButton, context: Context) {    }     func makeUIView(context: UIViewRepresentableContext<NFCWriteButton>) -> UIButton {         let button = UIButton()         button.setTitle("Write on Tag", for: .normal)         button.addTarget(context.coordinator, action: #selector(context.coordinator.beginScan(_:)), for: .touchUpInside)         return button     }     func makeCoordinator() -> NFCWriteButton.Coordinator {         return Coordinator(data: $data, toWrite: _dataToWrite)     }     class Coordinator: NSObject, NFCNDEFReaderSessionDelegate {         var session : NFCNDEFReaderSession?         @ObservedObject var dataToWrite: NFCDataSec = NFCDataSec()         @Binding var data: String         @ObservedObject var nfcData: NFCData         @objc func beginScan(_ sender: Any) {             guard NFCNDEFReaderSession.readingAvailable else {                 print("error: Scanning not support")                 return             }             session = NFCNDEFReaderSession(delegate: self, queue: .main, invalidateAfterFirstRead: true)             session?.alertMessage = "Hold your iphone near to scan."             session?.begin()         }         init(data: Binding<String>, toWrite: ObservedObject<NFCData>) {             _data = data             _nfcData = toWrite         }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’21
Reply to Networking error management
You usually use (your own) completion handler to tell error to the caller, but in your case, adding a new @Published property holding the error would be an alternative. So in my class I should be adding a @Published property variable to handle errors ? This is why I would like to implement a throw scenario to my request Button(action: {     self.showGroup = false     if (connexion.checkEmpty) { &#9;&#9;&#9;&#9;do {             try self.connect(url: "url")         } catch {             self.showError = true         } &#9;  } else {         self.showEmpty = true     } }) {     Text("button") } If iOS doesn't allow me to make throws is it better to make small functions for error management.             URLSession.shared.dataTask(with: request) { data, res, error in                 guard let httpResponse = res as? HTTPURLResponse,                         (200...299).contains(httpResponse.statusCode) else {                         self.handleServerError(res)                     return func handleServerError(_ res: URLResponse?) {     print("ERROR: Status Code: \(res!): the status code MUST be between 200 and 299") } Also, why can't I implement throws in my function when it is throwing ? func connect(url: String) throws { This is an exemple of the POST {"email":"XXXX@hell.com","password":"123456!"} Settings : KEY = Content-Type VALUE = application/json Here is and example of the dataString I'm receiving: [{"idTransfert":[],"_id":"60099ddc0eb9734ede9e831d","email":"test@test.eu","password":"4f8c9f9b94527112dbc","tokens":[{"_id":"60099de20eb9734ede9e8320","token":"eyJhbGciVCJ9.eyJfaWQ9.nEh2K7W0"},{"_id":"60099e160eb9734ede9e8323","token":"eyJhbGciOiJI.eyJfaWQiOiI2M9.nkJRk134b0"}],"sessions":[{"_id":"60099e160eb9734ede9e8325","sessionId":"nQIGGmN-766Z6nLwJBwSuLsQwlwP-WFu"}],"__v":2}] Here another version of my class: class Connexion: Codable, ObservableObject {     enum CodingKeys: String, CodingKey {         case email, password, id, token, sessionID     } /*   @Published var token: [Token] = [.init()] */ /*   @Published var sessionID: [SessionID] = [.init()]*/     @Published var token: String = ""     @Published var sessionID: String = ""     @Published var id: String = ""     @Published var email: String = ""     @Published var password: String = ""     init() {    }     required init(from decoder: Decoder) throws {         let container = try decoder.container(keyedBy: CodingKeys.self) /*        sessionID = try container.decode([SessionID].self, forKey: .sessionID)*/ /*        token = try container.decode([Token].self, forKey: .token)*/         sessionID = try container.decode(String.self, forKey: .sessionID)         token = try container.decode(String.self, forKey: .token)         id = try container.decode(String.self, forKey: .id)     }     func encode(to encoder: Encoder) throws {         var container = encoder.container(keyedBy: CodingKeys.self)         try container.encode(email, forKey: .email)         try container.encode(password, forKey: .password)     }     var checkEmpty: Bool {         if (email.isEmpty || password.isEmpty) {             return false         }         return true     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’21
Reply to Networking error management
I have this error when printing from line 44 of the code you send. Invalid response typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil)) - I don't have other setting Http Method: POST Body: raw: {"email":"XXXX@hell.com","password":"123456!"} Headers :  KEY = Content-Type VALUE = application/json Here is and example of the dataString I'm receiving from my request in my code: [ { "idTransfert":[]," _id":"60099ddc0eb9734ede9e831d", "email":"test@test.eu", "password":"4f8c9f9b94527112dbc", "tokens":[ { "_id":"60099de20eb9734ede9e8320", "token":"eyJhbGciVCJ9.eyJfaWQ9.nEh2K7W0" }, { "_id":"60099e160eb9734ede9e8323", "token":"eyJhbGciOiJI.eyJfaWQiOiI2M9.nkJR k134b0" } ], "sessions": [ { "_id":"60099e160eb9734ede9e8325", "sessionId":"nQIGGmN-766Z6nLwJBwSuLsQwlwP-WFu" } ], "__v":2 } ] API response: status 200 { &#9;&#9;"id": "5fc565209ce8b43c1315da9b", &#9;&#9;"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", &#9;&#9;"sessionID": "xiJOIhPj4l1qYz9uQRwAnWN38QBy12Qp" }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’21
Reply to Networking error management
I edited y Connexion Class: class Connexion: Codable, ObservableObject {     enum CodingKeys: String, CodingKey {         case email, password, id = "_id", token = "tokens", sessionID = "sessions", idTransfert     }     @Published var token: [Token] = [.init()] /* 1 */     @Published var sessionID: [SessionID] = [.init()] /* 1 */     @Published var idTransfert: [String] = []     @Published var id: String = ""     @Published var email: String = ""     @Published var password: String = "" } (1) they both have _id and token or sessionId depending on the class. But I think what could cause the error is the array [ { ... } ] of the JSON. I tried to make make an array from the Codingkey like so: let container = try decoder.container(keyedBy: [CodingKeys].self) But Instance method 'container(keyedBy:)' requires that '[Connexion.CodingKeys]' conform to 'CodingKey' Do have any ideas ? PS: tbh their API sucks a lot
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’21
Reply to Issue with networking and Codable class
Nearly, yes. Depends on the definition of dataToWrite. It works, the data are stored in the class. I have a question a bit similar, but I can't figure out the issue. Let me explain: I have a connection URL where I send my id and password and I'm supposed to GET id, sessionID and token but I always receive an invalid response (it is the same code as above). When I send the JSON with Postman I have no error ...
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’21
Reply to Issue with networking and Codable class
If you expect dataToWrite to be updated, you need to explicitly update it in the completion handler of dataTask. If I understand correctly and to be sure, I need to to it in this part of the function, where I check the server's response ? if let data = data {     let decoder = JSONDecoder()     print("this is what i'm retreiving from the API \(String(decoding: data, as: UTF8.self))")     if let json = try? decoder.decode(NFCDataSec.self, from: data) {         print(json)         print(self.dataToWrite.firstName)     } } And I need to do like so ?     if let json = try? decoder.decode(NFCDataSec.self, from: data) {         print(json)         self.dataToWrite.firstName = json.firstName     }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’21
Reply to Issue with networking and Codable class
Seems you have updated your last post. Yes sorry, I updated it because I forgot to change a type and it worked just after posting the first version. I forgot to tell it was updated. Where is the code updating your class? I thought by doing this line it would automatically update my class with the resent values if let json = try? decoder.decode(NFCDataSec.self, from: data)
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’21
Reply to Issue with networking and Codable class
I created a new variable @Published var stringAge: String = "" and edited my decoder with this new variable, and it is fixed. required init(from decoder: Decoder) throws { &#9;&#9;&#9;&#9;let container = try decoder.container(keyedBy: CodingKeys.self) &#9;&#9;&#9;&#9;lastName = try container.decode(String.self, forKey: .lastName) &#9;&#9;&#9;&#9;firstName = try container.decode(String.self, forKey: .firstName) /*&#9;&#9;&#9;age = try container.decode(Int.self, forKey: .age) */ &#9;&#9;&#9;&#9;stringAge = try container.decode(String.self, forKey: .age) } Here is a piece of mu function: if let data = data {                     let decoder = JSONDecoder()                     print("this is what i'm retreiving from the API \(String(decoding: data, as: UTF8.self))")                     if let json = try? decoder.decode(NFCDataSec.self, from: data) {                         print(json) /* (1) */                         print(self.dataToWrite.firstName) /* (2) */                     } Here is my console log: Encoded data: {"lastName":"John","firstName":"Paul","age":23} this is what i'm retreiving from the API {"firstName":"504ae2d3","lastName":"5244e2d626d03a7e8f","age":"3218"} Healthsafe.NFCDataSec&#9;/* (1) */ Paul /* (2) */ I can't understand, now, why my class is not updated with the retrieved data (2).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’21
Reply to Optional and onTapGesture
Do not put onTapGesture on Button and write all things to do in the action closure The onTapGesture is called properly when called for the NFCWriteButton. I may need to consolidate my code in order to make it cleaner and safer. Add action closure to your nfcWriteButton (in Swift, type names should start with Capital letter) like Button I forgot the capital letter, I put it everywhere else in my code. I will look how to do it with UIButton().addTarget method.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’21
Reply to SwiftUI : displaying a formatted dictionary from string.
So I tried earlier @Claude31 solution and I couldn't get it to work because I was changed it to class and also I did not really know how to bind it through multiple views -- It is fix now. :) I'm using the structure now and still using the Dictionary method you gave @OOPer. The issue I have, is not about the Optional(...) I guess. Let me show a piece of code: Here is what I gave you and will have to put in place : nfcWriteButton(data: $data)                 .onTapGesture {                     self.data = "lastName:\(self.deciphered["lastName"])\ngender:\(self.deciphered["gender"])\nfirstName:\(self.deciphered["firstName"])\nage:\(self.deciphered["age"])\n"                 } I was trying this at the same time :             Button(action: {                 print("\(self.nfcData.lastName)") /* 1 */ &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;print("\(String(describing: self.deciphered["lastName"])")) /* 1 */                 print(self.data) /* 2 */             }) {                 Text("UPDATE - test")             }                 .onTapGesture {                     self.data = "lastName:\(self.deciphered["lastName"])\ngender:\(self.deciphered["gender"])\nfirstName:\(self.deciphered["firstName"])\nage:\(self.deciphered["age"])\n" &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; print("self.data")                 } I noticed that (1) printed the updated value. Whereas (2) prints the data string as it got it, without the update made in the onTapGesture Then I also noticed that the print un the onTapGesture is never called. Is is normal because I'm doing this onTapGesture for the button and it won't accept it because there is already the action in the first part of the Button? Will it - the onTapGesture method - work for nfcWriteButton ? Here is the code of this button: struct nfcWriteButton : UIViewRepresentable {     @Binding var data: String     func updateUIView(_ uiView: UIButton, context: Context) {    }     func makeUIView(context: UIViewRepresentableContext<nfcWriteButton>) -> UIButton {         let button = UIButton()         button.setTitle("Write on Tag", for: .normal)         button.addTarget(context.coordinator, action: #selector(context.coordinator.beginScan(_:)), for: .touchUpInside)         return button     }     func makeCoordinator() -> nfcWriteButton.Coordinator {         return Coordinator(data: $data)     } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’21
Reply to SwiftUI : displaying a formatted dictionary from string.
I'm having an issue updating the dictionary now ... 😬 Do you have any idea ? The goal now is to reformat the data from the dictionary into string. I'm doing it like so : Button(action: {                 self.allowModifications = true                 print("\(String(describing: self.deciphered["lastName"])")) /* this line prints -> Optional("Paul") */             }) {                 Text("Edit")             } nfcWriteButton(data: $data)                 .onTapGesture {                     self.data = "lastName:\(self.deciphered["lastName"])\ngender:\(self.deciphered["gender"])\nfirstName:\(self.deciphered["firstName"])\nage:\(self.deciphered["age"])\n"                 } I also tried to silence the warning with String(describing: as Xcode suggested it but it does not change...
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’21
Reply to SwiftUI : displaying a formatted dictionary from string.
If I would need to access different value from my dictionary (like the code snippet here-under), will I need to return n times my HStack or my Form ? struct NFCMobileView: View {     @Binding var data: String     @State var decipheredString: String     var body: some View {         var deciphered = data.split(separator: "\n").reduce(into: [String: String]()) {             let str = $1.split(separator: ":")             if let first = str.first, let value = str.last {                 $0[String(first)] = String(value)             }         }         Form {             Group {                 HStack {                     Text("Last name")                     TextField("", text: deciphered["lastName"] ?? "")                 }                 HStack {                     Text("First name")                     TextField("", text: deciphered["firstName"] ?? "")                 }                 HStack {                     Text("Gender")                     TextField("", text: deciphered["gender"] ?? "")                 }                 HStack {                     Text("Age")                     TextField("", text: deciphered["Key3"] ?? "")                 } &#9;&#9;&#9;&#9;&#9;&#9;}         } &#9;&#9;} }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Dec ’20
Reply to Dictionary String:AnyObject : How to store in it from a String
Thank you for your different version and explication. I will use the following : var data = "Key0:Value\nKey1:Value\nKey2:Value\nKey3:Value\n" var deciphered = data.split(separator: "\n").reduce(into: [String: String]()) { &#9;&#9;&#9;&#9;&#9;&#9;let str = $1.split(separator: ":") &#9;&#9;&#9;&#9;&#9;&#9;if let first = str.first, let value = str.last { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$0[String(first)] = String(value) &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} The little issue I'm facing now, is to display the dictionary. I'm using SwiftUI for my app UI. Here is the code: struct NFCMobileView: View { &#9;&#9;@Binding var data: String &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;var deciphered = data.split(separator: "\n").reduce(into: [String: String]()) { &#9;&#9;&#9;&#9;&#9;&#9;let str = $1.split(separator: ":") &#9;&#9;&#9;&#9;&#9;&#9;if let first = str.first, let value = str.last { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;$0[String(first)] = String(value) &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;Text("Last Name") &#9;&#9;&#9;&#9;&#9;&#9;TextField("", text: deciphered["lastName"]) // error &#9;&#9;&#9;&#9;} &#9;&#9;} } Cannot convert value of type 'String?' to expected argument type 'Binding<String>' This is the error I'm having I'm getting the binding value data from what is on the NDEF tag
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Dec ’20