IOS Swift Unwrapping NSData is Crashing - ios

IOS swift problem while unwrapping, crashing. I am getting data as NSData, when I am printing in string or
var dict : AnyObject = NSJSONSerialization.JSONObjectWithData(returnData!, options: NSJSONReadingOptions(0), error: &respError) as AnyObject!
doing this its returning dict nil,
or
var datastring : NSString = NSString(data:returnData!, encoding:NSUTF8StringEncoding)[This is My Image Liknk] as! String
datastring causing fatal error:
unexpectedly found nil while unwrapping an Optional value.

You are unwrapping the values forcefully (Forced Unwrapping), If that object contains nil then it will generate runtime error.
Trying to use ! to access a non-existent optional value triggers a
runtime error. Always make sure that an optional contains a non-nil
value before using ! to force-unwrap its value.

You would do well to check all your values before you assume they're not nil. With the "!" you tell your code that this value can be safely unwrapped even though it may still be nil. Hence when it is nil, it crashes. What I usually do is:
// Unwrap the string, check if it ain't nil and store this in a new value.
if let content: String = item.content as? String {
if content != "" {
var error: NSError?
// Unwrap the data optional from dataUsingEncoding and also check if it ain't nil. Store this in a new value.
if let data: NSData = content.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true),
// Unwrap the optional returned from JSONObjectWithData and also check if it ain't nil. Store the value in a new object.
let json: NSMutableDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as? NSMutableDictionary {
// Do stuff with the dictionary.
} else {
if let err: NSError = error {
println(err.localizedDescription)
}
}
}
}
With all these checks I am sure my code will not crash deserializing the string to json in swift.
It appears I was a bit slow with my answer but Nilesh Patel has a good quote there which you should look at.

It is because returnData! is nil. If you put a break point at var dict, run and then po returnData! I believe you will find that to be true. And because the data at which NSJSONSerialization is trying to accept as a parameter is nil, it will be as well. I would go through your logic or your source to figure out why it is nil.
Also if you are using NSURLSession to retrieve your data - make sure you have a valid configured session before calling dataTaskWithURL. Like so...
var config = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: config)
var dataTask:NSURLSessionDataTask = session.dataTaskWithURL...
I ran into this problem and figured out that the session needed to be configured before I called the data task.
EDIT Also try this. Use optional binding.
if let data: NSDictionary = NSJSONSerialization.JSONObjectWithData(returnData, options: NSJSONReadingOptions.AllowFragments, error: nil) as? NSDictionary {
println("json = \(data)")
}
else {
println("returnData really is nil")
}

Related

Trying to add dictionary to nsmutable array in swift getting fatal error: unexpectedly found nil while unwrapping an Optional value

I am trying to create a NSMutableArray and add dictionary values from db (using fm db result set) then I got this error:
"fatal error: unexpectedly found nil while unwrapping an Optional value ".
Please give tips to solve this issue.
Code:
var arrCategory :NSMutableArray!
while rs.next(){
arrCategory.addObject(rs.resultDictionary())
}
In addition to checking that rs.resultDictionary isn't nil, make sure you have allocated the mutable array to begin with. In the code you posted, it is only declared:
var arrCategory:NSMutableArray!
...but it is not clear if you ever allocated it or not; e.g.:
arrCategory = NSMutableArray()
Also, there's a chanve rs is nil, not just resultDictionary (impossible to tell witohut seeing your full code), so perhaps the check should be:
if let rs = rs {
while rs.next(){
if let result = rs.resultDictionary {
arrCategory.addObject(result)
}
}
}
Before add dictionary, you should check that it is nil or not:
while rs.next(){
if(rs.resultDictionary() != nil){
arrCategory.addObject(rs.resultDictionary())
}
}
It is because you are putting nil in the NSMutableArray which is not allowed. Some where rs.resultDictionary is returning nil.If that should not be the case check that out. Meanwhile the following answer would work.
THE BETTER METHOD keeping in view the spirit of Swift language would be:
while rs.next()
{
if let result = rs.resultDictionary
{
arrCategory.addObject(result) ;
}
}

Swift Subscript Error

I believe it has something to do with optionals, but I'm safely unwrapping sourceURL so I'm still not sure where the error is! I'm trying to access a JSON object's array's dictionary value.
However, I'm still getting the "could not find overload for 'subscript' that accepts the supplied arguments.
It seems simple, but I just can't seem to figure it out!
var dictTemp: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &localError) as? NSDictionary
var finalURL: String
// error line below
if let sourceURL = dictTemp[0]["source"]["sourceUrl"] as? NSString {
finalURL = sourceURL as String
}
NSDictionary accessed from Swift is an interesting beast.
As long as Swift only knows something is an NSDictionary (not a more specific [Key: Value] Swift-style dictionary), you can only retrieve AnyObject?s out of it.
let dictTemp: NSDictionary = // from somewhere...
let step1 = dictTemp[0] // step1 is an AnyObject?
But then, since you've imported Foundation, you can keep going with a magical subscript operator that works on AnyObject, and checks whether the thing is a dictionary:
let step2 = step1?["source"] // step2 is any AnyObject??
Here's where it gets interesting, because
if step1 was a dictionary with a "source" key inside it, step2 will be the corresponding value.
if step1 was a dictionary without a "source" key, step2 will be nil — in particular, it's AnyObject??.Some(AnyObject?.None).
if step1 was nil (the original dictionary didn't have 0 as a key), or not a dictionary (it had a 0 key with some other kind of value), then step2 will be nil — in particular, AnyObject??.None.
(The distinction between the last 2 cases is mostly unimportant and you shouldn't worry about it, but if you're interested you can see it by using dump).
And of course, we can apply the same principle again:
let step3 = step2??["sourceUrl"] // step3 is AnyObject?? again
Now, binding them all in one if:
if let url = dictTemp[0]?["source"]??["sourceUrl"] as? String {
// do something with url...
}
Caveat
This type of syntax can be dangerous, since it works with arrays and dictionaries at the same time. What would you expect in these situations?
let dict: NSDictionary = [0: ["source": [3: "result"]]]
dict[0]?["source"]??[3] // returns nil (surprise!)
dict[0]?["source"]??[3 as NSNumber] // returns "result"
let dict2: NSDictionary = [0: ["source": [8, 7, 6, 5, 4]]]
dict2[0]?["source"]??[3] // returns 5
dict2[0]?["source"]??[3 as NSNumber] // returns nil (surprise!)

Swift - Cast from 'NSData?' to unrelated type 'NSDictionary' always fails

I'm on the newest version of Xcode and I'm getting this error: "Cast from 'NSData?' to unrelated type 'NSDictionary' always fails"
with this code:
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.dataWithJSONObject(dataObject!, options: nil, error: nil) as! NSDictionary
Programming Language: Swift
updated code:
if (error == nil) {
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as! NSDictionary
}
getting a breakpoint now when I run my app.
Sorry, i'm still new to stack overflow
Of course it fails. You're calling the wrong method.
The NSJSONSerialization method dataWithJSONObject takes an object that can be converted to JSON and returns NSData. It will always return NSData (or nil). It will never, under any circumstances, return a dictionary.
If you have NSData that you want to convert to a collection object then you want to use the method JSONObjectWithData instead.

Swift optionals and their instantiation

I'm new to Swift. I'll explain what I'm trying to do in Java terms and hopefully someone can help me understand.
I want a class scoped array that is instantiated/set in viewDidLoad of a view controller. It sounds simple enough, but this is what I had to do to get it to work. Could someone explain to me why the _dictionary must be instantiated as an empty array and why I need to use as? when unpacking dictionary even though the componentsSeparatedByString function returns an array? Thanks.
class ViewController: UIViewController, UITextFieldDelegate
{
var _dictionary : [String] = []
override func viewDidLoad()
{
super.viewDidLoad()
let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource(“TextFile”, ofType: "txt")
var err: NSError?
let dico = NSString(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: &err)
if let dictionary = dico?.componentsSeparatedByString("\n") as? [String]
{
_dictionary = dictionary
}
else
{
println("Error reading dictionary")
}
}
}
_dictionary must be given an initial value because all instance properties must be given an initial value. That is a Swift safety feature to make sure that all instances are well-formed at birth. You could have done this by initializing _dictionary in an actual initializer, but you didn't. You chose to give it its first "real" value in viewDidLoad which is much later. Therefore you have forced yourself to supply a "fake" initial value until such time as viewDidLoad comes along and gives you a "real" initial value.
I don't understand your other question because I don't know what "unpacking dictionary" means. But perhaps you are referring to the rest of the stuff in this code. I'll talk you through it.
dico is an Optional wrapping a String. It is an Optional because the contentsOfFile: initializer of String returns an Optional - it is a failable initializer. That is because there might be no such file, or that file might not have that encoding, in which case the initializer needs to return nil.
So now dico is an Optional wrapping a String that must be unwrapped - or nil. So you do unwrap it as dico? in the next line. dico? is a String at that point, assuming that dico was not nil.
Then you call componentsSeparatedByString. It returns an array of AnyObject. So you have chosen to cast it down to an array of String using as?. I don't know why you chose to use as? since you know it will be an array of String if we get to this point - personally, I would have used as. But in any case, as? always returns an Optional! So you unwrap that, optionally, by using an if let conditional binding.
The irony throughout is that _dictionary is not and never was or will be a dictionary - it is an array. Your name for this (and for dictionary) is very poorly chosen! dico is a String, and dictionary and _dictionary are arrays. There is not a dictionary in sight.
Assuming we keep your rather odd names, though, you could have done all this much more briefly and clearly, like this:
var err : NSError?
if let dico = NSString(contentsOfFile: path!,
encoding: NSUTF8StringEncoding, error: nil) {
_dictionary = dico.componentsSeparatedByString("\n") as [String]
} else {
println(err)
}
Moreover, if you start with the String class instead of the NSString class, then componentsSeparatedByString will be an array of String instead of an untyped NSArray (i.e. an array of AnyObject), and you can skip the cast:
var err : NSError?
if let dico = String(contentsOfFile: path!,
encoding: NSUTF8StringEncoding, error: nil) {
_dictionary = dico.componentsSeparatedByString("\n")
} else {
println(err)
}

unexpectedly found nil while unwrapping an Optional value when accessing dictionary with non-existent key

I'm trying to error handle the userInfo dictionary when receiving a remote push notification, in case the dictionary is missing an expected key. I keep getting an unexpectedly found nil while unwrapping an Optional value error when I try to do this:
if let message = userInfo["key_that_might_not_exist"] as? String {
// do something
}
I thought that if a key does not exist, it would be nil. What am I doing wrong here?
Try
if let message:String = a["key_that_might_not_exist"] {
// do something
}
is your userInfo really not nil?
if let userInfo = notification.userInfo as? Dictionary<String,NSObject> {
if let message = userInfo["key_that_might_not_exist"] as? NSString {
...
}
}
First of all, use a String; I do not think you need to have that specific thing as an NSString.
Second, are you sure userinfo exists? You could easily be setting the post wrong. Try wrapping it in:
if let dictionary = userInfo {
}

Resources