59

I am not sure if I am using the dictionary or the data object or both incorrectly. I m trying to get used to the switch to swift but I'm having a little trouble.

var dictionaryExample : [String:AnyObject] =
    ["user":"UserName",
     "pass":"password",
    "token":"0123456789",
    "image":0] // image should be either NSData or empty

let dataExample : NSData = dictionaryExample as NSData

I need the NSDictionary to encode to an NSData object as well as taking that NSData object and decode it into a NSDictionary.

Any help is greatly appreciated, thanks.

Stanislav Pankevich
  • 11,044
  • 8
  • 69
  • 129
IanTimmis
  • 815
  • 1
  • 8
  • 16
  • What are you actually trying to achieve? Saying "convert NSDictionary to NSData" is meaningless if you don't specify a format for the NSData. – gnasher729 Dec 24 '16 at 01:14

6 Answers6

114

You can use NSKeyedArchiver and NSKeyedUnarchiver

Example for swift 2.0+

var dictionaryExample : [String:AnyObject] = ["user":"UserName", "pass":"password", "token":"0123456789", "image":0]
let dataExample : NSData = NSKeyedArchiver.archivedDataWithRootObject(dictionaryExample)
let dictionary:NSDictionary? = NSKeyedUnarchiver.unarchiveObjectWithData(dataExample)! as? NSDictionary

Swift3.0

let dataExample: Data = NSKeyedArchiver.archivedData(withRootObject: dictionaryExample)
let dictionary: Dictionary? = NSKeyedUnarchiver.unarchiveObject(with: dataExample) as! [String : Any]

Screenshot of playground

enter image description here

Capella
  • 881
  • 3
  • 19
  • 32
Leo
  • 24,596
  • 11
  • 71
  • 92
  • You did answer my question specifed in the title. I think AnyObject was wrong. I want to have the user/pass/token be strings and the image be an nsdata object. Am I able to do that? or should i encode them all into NSData objects and then decode them afterwards? – IanTimmis Oct 15 '14 at 07:23
  • class func unarchiveObjectWithData(data: NSData) -> AnyObject? This is from the doc of xocde. – Leo Oct 15 '14 at 07:26
  • Nevermind when i end up using them i just say data.valueForKey("user") as string Thanks for the help this thread can now close – IanTimmis Oct 15 '14 at 07:31
  • This doesn't work. This produces error `'AnyObject' is not convertible to 'NSDictionary';` – c.dunlap Mar 31 '16 at 15:14
  • @c.dunlap I have update the code. I answered the answer when it is swift 1.2. So,for swift 2.0,it may have some syntax issue – Leo Mar 31 '16 at 15:24
  • This does not work because the function unarchiveObject(with:) takes a variable of type Data, whereas the function unarchiveTopLevelObjectWithData() takes a variable of type NSData. See my answer – Ujjwal-Nadhani Dec 23 '16 at 08:33
11

Swift 5

as @yuyeqingshan said, PropertyListSerialization is a good option

       // Swift Dictionary To Data.
        do {
            let data = try PropertyListSerialization.data(fromPropertyList: [:], format: PropertyListSerialization.PropertyListFormat.binary, options: 0)
            // do sth
        } catch{
            print(error)
        }


        // Data to Swift Dictionary
        do {
            let dicFromData = try PropertyListSerialization.propertyList(from: data, options: PropertyListSerialization.ReadOptions.mutableContainers, format: nil)
            if let dict = dicFromData as? [String: Any]{
                // do sth
            }
        } catch{
            print(error)
        }
DNG
  • 599
  • 4
  • 14
9

NSPropertyListSerialization may be an alternative solution.

// Swift Dictionary To Data.
var data = try NSPropertyListSerialization.dataWithPropertyList(dictionaryExample, format: NSPropertyListFormat.BinaryFormat_v1_0, options: 0)

// Data to Swift Dictionary
var dicFromData = (try NSPropertyListSerialization.propertyListWithData(data, options: NSPropertyListReadOptions.Immutable, format: nil)) as! Dictionary<String, AnyObject>
yuyeqingshan
  • 381
  • 3
  • 13
3

For Swift 3:

let data = try PropertyListSerialization.data(fromPropertyList: authResponse, format: PropertyListSerialization.PropertyListFormat.binary, options: 0)
Nikolaj Simonsen
  • 1,650
  • 3
  • 18
  • 34
ingconti
  • 10,876
  • 3
  • 61
  • 48
3

Leo's answer gave me build time errors because NSData isn't the same as Data. The function unarchiveObject(with:) takes a variable of type Data, whereas the function unarchiveTopLevelObjectWithData() takes a variable of type NSData.

This is a working Swift 3 answer:

var names : NSDictionary = ["name":["John Smith"], "age": 35]
let namesData : NSData = NSKeyedArchiver.archivedData(withRootObject: names) as NSData
do{
    let backToNames = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(namesData) as! NSDictionary
    print(backToNames)
}catch{
    print("Unable to successfully convert NSData to NSDictionary")
}
Community
  • 1
  • 1
Ujjwal-Nadhani
  • 613
  • 2
  • 9
  • 20
-3

For Swift 4 -

let dictionaryExample : [String:AnyObject] = ["user":"UserName" as AnyObject, "pass":"password" as AnyObject, "token":"0123456789" as AnyObject, "image":0 as AnyObject]
    let dataExample : NSData = NSKeyedArchiver.archivedData(withRootObject: dictionaryExample) as NSData
    let dictionary:NSDictionary? = NSKeyedUnarchiver.unarchiveObject(with: dataExample as Data)! as? NSDictionary
Abhishek Mishra
  • 1,625
  • 16
  • 32
  • 4
    Bad example. You say "Swift 4" but you're casting NSData to Data instead of using Data directly, you're using AnyObject instead of Any, and your usage of optionals is far from optimal... – Eric Aya May 15 '18 at 08:28