Dictionary String:AnyObject : How to store in it from a String

Hello dear readers,

I'm having an issue with dictionaries.
I am receiving this from my NDEF tag: Key0:Value\nKey1:Value\nKey2:Value\nKey3:Value\n
The values can be ether String or Int.
I would like to create a dictionary with these keys and values.

I have written this code for now:
Code Block Swift
let deciphered = str.split(separator: "\n").reduce(into: [String: AnyObject]()) {
let str = $1.split(separator: ":")
if let first = str.first, let key = String(first), let value = str.last {
$0[key] = value as AnyObject
}
}


I also tried this:
Code Block
let split = str.split(whereSeparator: \.isNewline)

Where str is my string of all values. But I'm stuck with the : between the Key and Value

But I'm having this error:
Code Block
error: initializer for conditional binding must have Optional type, not 'String'
if let first = str.first, let key = String(first), let value = str.last {
^ ~~~~~~~~~~~~~


Can you help me or give me an other way to store it ?

The idea after is to modify the value and send it back on a NDEF tag.

Thank you for your help
Answered by OOPer in 654599022
You can write your code without using let key:
Code Block
import Foundation
let str = "Key0:Value\nKey1:Value\nKey2:Value\nKey3:Value\n"
let deciphered = str.split(separator: "\n").reduce(into: [String: AnyObject]()) {
let str = $1.split(separator: ":")
if let first = str.first, let value = str.last {
$0[String(first)] = value as AnyObject
}
}
print(deciphered)
//-> ["Key0": Value, "Key1": Value, "Key3": Value, "Key2": Value]


If you insist on using let key, you can write it as:
Code Block
let deciphered = str.split(separator: "\n").reduce(into: [String: AnyObject]()) {
let str = $1.split(separator: ":")
if let first = str.first, let value = str.last {
let key = String(first)
$0[key] = value as AnyObject
}
}


If you dare move it inside if:
Code Block
let deciphered = str.split(separator: "\n").reduce(into: [String: AnyObject]()) {
let str = $1.split(separator: ":")
if let first = str.first, case let key = String(first), let value = str.last {
$0[key] = value as AnyObject
}
}

But I do not recommend this as case let key = String(first) is not working as a condition.
first is a subString, String(first) is not an optional, so if let does not work.

I changed as follows:

Code Block
let nfcStr = "Key0:Value\nKey1:Value\nKey2:Value\nKey3:Value\n"
let deciphered = nfcStr.split(separator: "\n").reduce(into: [String: AnyObject]() {
let str = $1.split(separator: ":")
if let first = str.first, let value = str.last {
let key = String(first)
$0[key] = value as AnyObject
}
}
print(deciphered)

And get:
["Key2": Value, "Key3": Value, "Key1": Value, "Key0": Value]

Note: it is a dict, so not ordered of course.

Is it what you'd expect ?
If so, don't forget to close the thread on the correct answer.

Accepted Answer
You can write your code without using let key:
Code Block
import Foundation
let str = "Key0:Value\nKey1:Value\nKey2:Value\nKey3:Value\n"
let deciphered = str.split(separator: "\n").reduce(into: [String: AnyObject]()) {
let str = $1.split(separator: ":")
if let first = str.first, let value = str.last {
$0[String(first)] = value as AnyObject
}
}
print(deciphered)
//-> ["Key0": Value, "Key1": Value, "Key3": Value, "Key2": Value]


If you insist on using let key, you can write it as:
Code Block
let deciphered = str.split(separator: "\n").reduce(into: [String: AnyObject]()) {
let str = $1.split(separator: ":")
if let first = str.first, let value = str.last {
let key = String(first)
$0[key] = value as AnyObject
}
}


If you dare move it inside if:
Code Block
let deciphered = str.split(separator: "\n").reduce(into: [String: AnyObject]()) {
let str = $1.split(separator: ":")
if let first = str.first, case let key = String(first), let value = str.last {
$0[key] = value as AnyObject
}
}

But I do not recommend this as case let key = String(first) is not working as a condition.
Thank you for your different version and explication.

I will use the following :
Code Block Swift
var data = "Key0:Value\nKey1:Value\nKey2:Value\nKey3:Value\n"
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)
}
}

The little issue I'm facing now, is to display the dictionary. I'm using SwiftUI for my app UI.

Here is the code:
Code Block Swift
struct NFCMobileView: View {
@Binding var data: 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)
}
}
HStack {
Text("Last Name")
TextField("", text: deciphered["lastName"]) // error
}
}
}

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
As you closed the thread, you should open a new thread with the new question, in order to avoid never ending post.

But may be it is simply that deciphered["lastName"] is optional
So replace with

Code Block
TextField("", text: deciphered["lastName"] ?? "")

Sorry

I opened this new request, with the edits you suggested : https://developer.apple.com/forums/thread/670309
Dictionary String:AnyObject : How to store in it from a String
 
 
Q