1

I have create class Testing model which has 4 dataMember it should not be null when accessing (means return default value)

extension Double {
    /// Rounds the double to decimal places value
    func roundTo(places:Int = 2) -> Double
    {
        let divisor = pow(10.00, Double(places))
        return (self * divisor).rounded() / divisor
    }
}
class TestingModel{

    var id : String!
    var name : String! = "abc" /*It is not working*/
    var price : Double! = 0.00
    var uniqueId : Int! = 1


    /**
     * Instantiate the instance using the passed dictionary values to set the properties values
     */
    init(dictionary: [String:Any])
    {
        id = (dictionary["id"] as? String) ?? "" //I dont want to do like this way
        name = dictionary["name"] as? String
        price = (dictionary["price"] as? Double)?.roundTo() ?? 0.00
        uniqueId = dictionary["unique_id"] as? Int
    }

}

let t:TestingModel = TestingModel.init(dictionary: ["x id" : "x012y12345z45","x name":"test1","x price":100.0,"uniqueId":1236.0])
let testString = "Jd " + t.id
print(testString) //Perfect
print(t.name)
print(t.price) /* Only one decemal point is printed */

Getting Output

Jd 
nil
0.0

Expected output

Jd

abc /Should return abc instead of nil/

0.00 /Two decimal point complulsury/

What i actually mean in

if i assign nil value to variable then it should remain with its default value without writing this Optional chaining ?? "abc" in constructor

Jaydeep Vyas
  • 4,411
  • 1
  • 18
  • 44

2 Answers2

1

price is a Double type and what you are asking to do is to print that double value to 2 decimal places. Then you should make use of the following.

let a = 0.0
print(String(format: "%.2f", a))

this prints:

0.00

If you are planning to round it to decimal places, then also the above code will return that. But if you need it to round and return a double type then you can check this answer

Based on your updated question, I suggest to use the model as follows:

class TestingModel{
    var id : String = ""
    var name : String = "abc" 
    var price : Double = 0.0
    var uniqueId : Int = 1

    /**
     * Instantiate the instance using the passed dictionary values to set the properties values
     */
    init(dictionary: [String:Any])
    {
        id = (dictionary["id"] as? String) ?? "" 
        name = dictionary["name"] as? String ?? "abc"
        price = (dictionary["price"] as? Double) ?? 0.0
        uniqueId = dictionary["unique_id"] as? Int ?? 1
    }
}
adev
  • 2,052
  • 1
  • 21
  • 33
  • What is the difference between `0` and `0.00`? For a `Double` type both are same. Only while printing you tell it to show the number of decimal points required. – adev Aug 06 '17 at 05:12
  • I think you are confused between a string printed in console and your Double type. double doesn't control how many zeroes are present after `.`. Only while printing or converting to string, you can get the required number of zeroes printed. – adev Aug 06 '17 at 05:16
  • That is because you do the rounding on a floating number that big. But for `0`, you cant do that. It will return `0.0` – adev Aug 06 '17 at 05:18
  • You cant avoid `??` which sets default values instead of `nil`. It is a swift language feature. So nothing can be done about that. – adev Aug 06 '17 at 05:22
  • upvoting you for nice explaination – Jaydeep Vyas Aug 06 '17 at 06:05
0

You seem to have asked two different questions here. The first one regarding doubles have already been answered by adev. I will answer the second one, which is:

if i assign nil value to variable then it should remain with its default value without writing this Optional chaining ?? "abc" in constructor

If you want to do this then it means that the variable shouldn't be optional at all, as nil isn't one of its valid values. Make the variable a non-optional type and give it a default value.

class TestingModel{

    var id : String = ""
    var name : String = "abc"
    var price : Double = 0.00
    var uniqueId : Int = 1
}

You can't really avoid using ?? in the constructor because of the nature of dictionaries. They will always return a nil value if the key does not exist. You have to check it. It does not make sense even if this is possible anyway. Imagine something like this:

someVariable = nil // someVariable is now 0

This is extremely confusing. someVariable is 0, even though it appears that nil is assigned to it.

A workaround will be to add a dictionary extension. Something like this:

extension Dictionary {
    func value(forKey key: Key, defaultValue: Value) -> Value {
        return self[key] ?? defaultValue
    }
}

But I still recommend that you use ?? instead.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • why extesion Dictionary is not better way any reason (it looks more readable format) – Jaydeep Vyas Aug 06 '17 at 06:31
  • @JaydeepVyas Because the extension is basically a wrapper of the `??` operator. There is already `??`, don't you think the extension is kind of "reinventing the wheel"? Anyone who has some degree of experience in swift knows what `??` does and your current code is pretty clear. There is no need to think of a way to avoid using `??`. `??` is designed for exactly this purpose after all. – Sweeper Aug 06 '17 at 06:38
  • I had mentioned the same in now deleted chat room on my answer. He cant avoid `??`. – adev Aug 06 '17 at 07:05
  • Can you answer my other question at https://stackoverflow.com/q/45483376/6028575 Which is put on hold – Jaydeep Vyas Aug 06 '17 at 08:31
  • And also here I have answered my self by using extension of double which is valid or not??? – Jaydeep Vyas Aug 06 '17 at 08:34
  • @JaydeepVyas I think the answers in that post are pretty good already, what do you want to know? – Sweeper Aug 06 '17 at 08:34
  • i want to know is extension are only for readability nothing else ??(Surprised) – Jaydeep Vyas Aug 06 '17 at 15:10
  • In the two cases of your question, yes. Sometimes you want a class to conform to a protocol but you can't edit the class' source code. Then you can use extensions to make it conform to that protocol. @JaydeepVyas – Sweeper Aug 06 '17 at 15:19
  • but in swift 4 we can access private member also in extension so we can change the source code – Jaydeep Vyas Aug 06 '17 at 15:27