84

I have made a request to my server in my app. And posted data something like this.Server side is waiting for all parameters even they are nil. But i couldn't add nil values to dictionary.

 var postDict = Dictionary<String,AnyObject>
 postDict[pass]=123
 postDict[name]="ali"
 postDict[surname]=nil // dictionary still has only pass and name variables.

Is there a way to add nil value to dictionary ?

mfaani
  • 33,269
  • 19
  • 164
  • 293
yatanadam
  • 1,254
  • 1
  • 11
  • 19

9 Answers9

131

How to add nil value to Swift Dictionary?

Basically the same way you add any other value to a dictionary. You first need a dictionary which has a value type that can hold your value. The type AnyObject cannot have a value nil. So a dictionary of type [String : AnyObject] cannot have a value nil.

If you had a dictionary with a value type that was an optional type, like [String : AnyObject?], then it can hold nil values. For example,

let x : [String : AnyObject?] = ["foo" : nil]

If you want to use the subscript syntax to assign an element, it is a little tricky. Note that a subscript of type [K:V] has type V?. The optional is for, when you get it out, indicating whether there is an entry for that key or not, and if so, the value; and when you put it in, it allows you to either set a value or remove the entry (by assigning nil).

That means for our dictionary of type [String : AnyObject?], the subscript has type AnyObject??. Again, when you put a value into the subscript, the "outer" optional allows you to set a value or remove the entry. If we simply wrote

x["foo"] = nil

the compiler infers that to be nil of type AnyObject??, the outer optional, which would mean remove the entry for key "foo".

In order to set the value for key "foo" to the AnyObject? value nil, we need to pass in a non-nil outer optional, containing an inner optional (of type AnyObject?) of value nil. In order to do this, we can do

let v : AnyObject? = nil
x["foo"] = v

or

x["foo"] = nil as AnyObject?

Anything that indicates that we have a nil of AnyObject?, and not AnyObject??.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • This solution is so much more Swifty than `NSNull()`! – Franklin Yu May 11 '16 at 17:39
  • 1
    It's a little easier to use and more readable if you define this "Null" object as a constant:`static let NullObject: AnyObject?? = Optional(nil)` – Raginmari Jul 04 '16 at 12:12
  • 15
    Whose bright idea was it that assigning nil to a dictionary entry means remove the entry, even when nil is a valid entry when the dictionary is defined as having AnyObject? or Any? entries? That just cost me several hours and lowered my opinion of Swift a couple of notches. – RenniePet Jan 11 '17 at 02:15
  • 2
    The correct answer is the one from Guiller, by setting nil a value using subscript you remove the value anche the key, while using the function `updateValue` you can set the value to nil while keeping the key. – Andrea Mar 01 '17 at 11:08
  • Good point. It's confusing, but the point is indeed use `= nil as Foo?`. – Jakub Truhlář Mar 01 '18 at 16:55
  • x["foo"] = nil will delete the entry "foo". x["foo"]! = nil will se the value of the entry "foo" to nil. x["bar"] = nil will not insert any entry. x["bar"]! = nil will blow up. x.updateValue( nil, forKey: "bar" ) will add entry "bar" to x with value nil, as pointed in the @Guiller answer. – user2101384 Apr 06 '21 at 10:45
  • x["foo"] = nil as Any? also works. But I think updateValue(nil, forKey: "foo") is easier to understand for people who is junior or getting started with swift. – user2101384 Apr 06 '21 at 11:07
56

You can use the updateValue method:

postDict.updateValue(nil, forKey: surname)
shim
  • 9,289
  • 12
  • 69
  • 108
Guiller
  • 621
  • 5
  • 2
  • 2
    Dont know why this is downvoted but this is the best way to do it imho. – ramazan polat Sep 24 '16 at 23:27
  • This is the best answer I have ever seen on SA. You should be gifted with 1 million battles of wine;) I have created a bounty and I will award it to you within 24 hours;) – Bartłomiej Semańczyk Dec 21 '17 at 21:37
  • @BartłomiejSemańczyk: Then you should have chosen *"One or more of the answers is exemplary and worthy of an additional bounty."* as the bounty reason. Now it looks as if you are looking for another/better answer. – Martin R Dec 22 '17 at 08:11
  • @MartinR you are right, I would change the reason of bounty but I cannot. Nice learn to me;) – Bartłomiej Semańczyk Dec 22 '17 at 08:51
26

As documented in here, setting nil for a key in dictionary means removing the element itself.

If you want null when converting to JSON for example, you can use NSNull()

var postDict = Dictionary<String,AnyObject>()
postDict["pass"]=123
postDict["name"]="ali"
postDict["surname"]=NSNull()

let jsonData = NSJSONSerialization.dataWithJSONObject(postDict, options: NSJSONWritingOptions.allZeros, error: nil)!
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)!
// -> {"pass":123,"surname":null,"name":"ali"}
Jacob Rau
  • 25
  • 5
rintaro
  • 51,423
  • 14
  • 131
  • 139
5
postDict[surname] = Optional<AnyObject>(nil)
Vatsal Manot
  • 17,695
  • 9
  • 44
  • 80
  • In most (all?) cases you don't even need the ``. It should be able to infer the type. – Max Jan 21 '19 at 17:52
4

Below dictionary will hold one key with nil value

var dict = [String:Any?]()
dict["someKey"] = nil as Any?
Hiren Panchal
  • 2,963
  • 1
  • 25
  • 21
3

You can use the Optional type

var postDict = ["pass": 123, "name": "ali", "surname": Optional()]
Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
Priya Raj
  • 71
  • 1
  • 5
2

To add a nil value to a dictionary in Swift, your dictionary's values must be of the Optional type.

Consider a Person class:

class Person {
    let name: String
    weak var spouse: Person?

    init(name: String, spouse: Person?) {
        self.name = name
        self.spouse = spouse
    }
}

Instances of the Person type can have a name and an optional spouse. Create two instances, and add the first to a dictionary:

let p1 = Person(name: "John", spouse: nil)
let p2 = Person(name: "Doe", spouse: p1)
p1.spouse = p2
var people = [p1.name: p1.spouse]

This dictionary (called people) maps names to spouses, and is of type [String: Person?]. You now have a dictionary with a value of Optional type: Person?.

To update the value of the key p1.name to be nil, use the updateValue(_: forKey:) method on the Dictionary type.

people.updateValue(nil, forKey: p1.name)
people[p1.name] 

The value for the key p1.name is now nil. Using updateValue(_: forKey:) is a bit more straightforward in this case because it doesn't involve making a throwaway instance, setting it to nil, and assigning that instance to a key in a dictionary.

NB: See rintaro's answer for inserting null into a post's dictionary.

Matt Mathias
  • 932
  • 7
  • 7
2
var dict = [Int:Int?]()

dict[0] = (Int?).none // <--- sets to value nil

dict[0] = nil         // <-- removes

dict[0] = .none       // <-- same as previous, but more expressive

switch dict[0] {
case .none:
    Swift.print("Value does not exist")

case .some(let value):
    if let value = value {
        Swift.print("Value exists and is", value)
    } else {
        Swift.print("Value exists and is nil")
    }
}
user3763801
  • 395
  • 4
  • 10
1
postDict[surname]=nil

When you use subscript to set nil. It deletes the key if exists. In this case key surname will be removed from dictionary if exists.

To set value as nil, there are certain ways.

postDict.updateValue(nil, forKey: surname)

or

let anyObjectNil : AnyObject? = nil
postDict[surname] = anyObjectNil

or

postDict[surname] = nil as AnyObject?
vntstudy
  • 2,038
  • 20
  • 24