0

Double in an object converts to a string (or just goes into quotation marks) when added in another object. I don't want this behavior. I want the double to remain as double so that my database rules work perfectly

var list: [String: AnyObject] = [:]

var obj: [String: Any] = [:]
obj["pi"] = 3.14
obj["test"] = "hello"

list["firstObj"] = obj as AnyObject

print(list)

This is the result:

["firstObj": { pi = "3.14"; test = hello; }]

I want this

["firstObj": { pi = 3.14; test = hello; }]

Please suggest what can I do to achieve the desired result

Note: You can run this code in playground to check.

Edited

The question is still unresolved. After following the answers I made the model and posted it to my firebase. Now this is the exception I get in return

'InvalidFirebaseData', reason: '(setValue:withCompletionBlock:) Cannot store object of type _SwiftValue at cardCost. Can only store objects of type NSNumber, NSString, NSDictionary, and NSArray.'

I want to make it firebase readable

Moaz Khan
  • 1,272
  • 1
  • 13
  • 28
  • 2
    Create a custom model instead of declaring `obj` as `[String: Any]`. – Ahmad F Apr 25 '18 at 09:55
  • 1
    What exactly you want to achieve? The `pi` in your dictionary is still a `Double`, it's just the way it gets printed. Disregarding storing your data model as dictionary of course – mag_zbc Apr 25 '18 at 10:01
  • My firebase rules don't let me post this @mag_zbc – Moaz Khan Apr 25 '18 at 10:02
  • Good tip for you. If you change a question after it has been answered. Let the people answering know by commenting. Don't just down vote them. Also... avoid changing questions after they have been answered. – Fogmeister Apr 25 '18 at 13:51

2 Answers2

2

obj["pi"] is a Double. You can test this out as follows…

var list: [String: Any] = [:]
var obj: [String: Any] = [:]
obj["pi"] = 3.14
obj["test"] = "hello"    
list["firstObj"] = obj as Any

func printTypesFor(dict: [String: Any]) {
    for (key, value) in dict {
        print(key + " is a " + "\(type(of: value))")
        if let valueDict = value as? [String: Any] {
            printTypesFor(dict: valueDict)
        }
    }
}

printTypesFor(dict: list)


firstObj is a Dictionary<String, Any>
test is a String
pi is a Double
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
  • 3
    This is the only answer that actually answers the original question – mag_zbc Apr 25 '18 at 10:06
  • 1
    @mag_zbc yes, it answers the question and encourages bad practices of using non-typed data objects... great... – Fogmeister Apr 25 '18 at 10:32
  • 1
    @Fogmeister This doesn't encourage any practice, good or bad - it just attempts answers the question. – Ashley Mills Apr 25 '18 at 10:36
  • 1
    "Please suggest what can I do to achieve the desired result" ... don't use Dictionaries to store data. Why does the suggestion of "use structs and typed properties" deserve 3 downvotes? (when it also had 4 up votes?!?) – Fogmeister Apr 25 '18 at 10:38
  • Well, per his additional comment, he's posting to Firebase, which requires a dictionary. Downvotes for your answer seem harsh though. – Ashley Mills Apr 25 '18 at 11:05
  • @AshleyMills you mean his comment and edit to the question that were added after my answer and change the question completely. Yeah... would’ve been better to not change the question or at least to comment on answers that the goalposts were moved rather than down voting them multiple times. – Fogmeister Apr 25 '18 at 11:15
0

Although I agree with Ashley Mills's answer:

obj["pi"] is a Double

I would recommend to "Templating" it instead of working with dictionaries, it leads to avoiding the manual type casting and ensuring type safety. You could create a custom model and let obj to be of type of this model. Example:

struct MyModel {
    var pi: Double
    var test: String
}

then declare obj as:

var obj = MyModel(pi: 3.14, test: "hello")

therefore, list could be declared as:

var list = [MyModel]()

instead of being declared as [String: AnyObject].

Ahmad F
  • 30,560
  • 17
  • 97
  • 143