Found nil while unwrapping optional value JSON Serialization - php

I perform a NSURLSession to get data from a php, which is a JSON. When I do NSJSONSerialization and store it as a NSArray everything works fine but when I try to access an element of it to put it in a table view it crashes with the error found nil while unwrapping an optional value. The JSON it returns looks like this:
[
{
"title":"data",
"value":"data"
}, ...
]
The code I'm using to get the value is:
self.arrayJSON[indexPath.row]["title"]
And when I try this in the Xcode console returns this:
▿ Optional(some data)
- Some : some data
EDIT:
JSON parsing code:
let task = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
do {
let responseJSON : NSArray = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! NSArray
self.arrayJSON = NSMutableArray(array: responseJSON)
dispatch_async(dispatch_get_main_queue()) {
self.listaAnuncios.reloadData()
}
} catch {
print("json error")
}
}
task.resume()

I found the problem! It wasn't because of accessing to the element, it was because the cell was nil. I was using this:
let cell : CustomCell = CustomCell()
and I changed it for this:
let cell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! CustomCell

Related

I have this issue when trying to read my data which is json encoded from the php page to the swift page

I have this issue when trying to read my data which is json encoded from the php page to the swift page.
this is the code I am using
import Foundation
protocol HomeModelProtocol: class {
func itemsDownloaded(items: NSArray)
}
class HomeModel: NSObject, URLSessionDataDelegate {
//properties
weak var delegate: HomeModelProtocol!
var data = Data()
let urlPath: String = "http://localhost/service.php" //this will be changed to the path where service.php lives
func downloadItems() {
let url: URL = URL(string: urlPath)!
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Failed to download data")
}else {
print("Data downloaded") // this work fine
self.parseJSON(data!)
}
}
task.resume()
}
func parseJSON(_ data:Data) {
var jsonResult = NSArray()
print(jsonResult) // this print empty parentheses
print(String(data: data, encoding: .utf8)) // this prints out the array
//the code below throughs an arror
do{
jsonResult = try JSONSerialization.jsonObject(with:data, options:JSONSerialization.ReadingOptions.allowFragments) as! [NSArray] as NSArray
print(jsonResult)
} catch let error as NSError {
print(error)
}
var jsonElement = NSDictionary()
let locations = NSMutableArray()
for i in 0 ..< jsonResult.count
{
jsonElement = jsonResult[i] as! NSDictionary
let location = LocationModel()
//the following insures none of the JsonElement values are nil through optional binding
if let name = jsonElement["Name"] as? String,
let address = jsonElement["Address"] as? String,
let latitude = jsonElement["Latitude"] as? String,
let longitude = jsonElement["Longitude"] as? String
{
location.name = name
location.address = address
location.latitude = latitude
location.longitude = longitude
}
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(items: locations)
})
}
}
this is the output which I am receiving:
Data downloaded
(
)
Optional(" \nconnectedinside[{\"name\":\"One\",\"add\":\"One\",\"lat\":\"1\",\"long\":\"1\"},{\"name\":\"Two\",\"add\":\"Two\",\"lat\":\"2\",\"long\":\"2\"},{\"name\":\"One\",\"add\":\"One\",\"lat\":\"1\",\"long\":\"1\"},{\"name\":\"Two\",\"add\":\"Two\",\"lat\":\"2\",\"long\":\"2\"}]")
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around
character 2." UserInfo={NSDebugDescription=Invalid value around
character 2.}
You get this error, because the json response you receive is not an array but a dictionary.
EDIT: as pointed out in a comment, you first need to fix your json response in your php code. There is ":" missing after "connectedinside".
It should look like this:
{\"connectedinside\":[{\"name\":\"One\",\"add\":"One",...},...]}
My suggestion to fix this:
You should have two models:
struct HomeModelResponse: Codable {
let connectedinside: [LocationModel]
}
// your LocationModel should look like this:
struct LocationModel: Codable {
let name: String
let add: String
let lat: String
let long: String
}
And change your JSONDecoding code to:
do {
jsonResult = try? JSONDecoder().decode(HomeModelResponse.self, from: data)
print()
} catch let exception {
print("received exception while decoding: \(exception)"
}
Then you can access your LocationModels by jsonResult.connectedinside
The problem was on my php side and I fixed it.it is working now.

Cannot convert value of type '(NSData?, URLResponse?, NSError?) -> ()' to expected argument type '(Data?, URLResponse?

Hi all I am trying my hands on Swift and I am trying to post users registration data. I know how to do it firebase but my main project is in php mysql so I want to connect it with swift
#IBAction func signUp(_ sender: Any) {
//check textfield data
checkTextFields()
//create user
let url = NSURL(string: "http://localhost:8888/helo/register.php")
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "POST"
//apending body to url
let body = "Fullname=\(name.text!.lowercased())&userName=\(userName.text!.lowercased())&emailAddress=\(emailAddress.text!.lowercased())&password=\(password.text!.lowercased())"
request.httpBody = body.data(using: String.Encoding.utf8)
//lunching
URLSession.shared.dataTaskWithRequest(request as URLRequest, completionHandler: { (data:NSData?, response:URLResponse?, error:NSError?) in
if error == nil{
dispatch_async(dispatch_get_main_queue(),{
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as?
NSDictionary
guard let parseJSON = json else{
print("Error while parsing")
return
}
let id = parseJSON["id"]
if id != nil {
print(parseJSON)
}
}catch{
print("Caugth an error: \(error)")
}
})
}else{
print("error: \(error)")
}
} )
}
I am getting an error on the line where I have commented as as lunching which say
Cannot convert value of type '(NSData?, URLResponse?, NSError?) -> ()' to expected argument type '(Data?, URLResponse?, Error?) -> Void'
I am new to Swift any help is welcome thank you all. I am using Xcode 9
After enough reading, I just realised I was doing a very tedious and using orthodox method when things have improved. I removed the whole code and did everything with Alamofire. Its really easy and straight forward. I will post the code below to help others who encounter similar problems later on.
//Constant that holds the URL for our web servicer
let URL_USER_REGISTER = "http://localhost:8888/members/register.php?"
Alamofire.request(URL_USER_REGISTER, method: .post, parameters: parameters).responseJSON{
response in
//printing response
print(response)
//getting json value from the server
if let result = response.result.value {
//converting it as NSDictionary
let jsonData = result as! NSDictionary
//displaying the message in label
self.lableMessage.text = jsonData.value(forKey: "message") as! String?
}
}
you have to first import Alamofire.

Trying to Parse JSON in swift but not working

I'm trying to parse some JSON, this is what it's returning when I directly go to the URL:
[{"Password":"whatever1"}]
My code is able to receive the data correctly (when I debugged the variable "data" had the above JSON) however when trying to Parse it, it won't work. I think it might have to do with the square brackets, cause I've been parsing other JSONs without the square brackets and it works well.
Here is my code:
func SignIn (username: String, password: String, completion: #escaping (Bool)->())
{
let url = URL(string: "http://<myIP>/API/SignIn.php?username=\(username)");
let task = URLSession.shared.dataTask(with: url!)
{ (data, response, error) in
if let data = data
{
do
{
// Convert the data to JSON
let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
// print( jsonSerialized)
if let json = jsonSerialized, let result = json["Password"]
{
print(result)
if (String(describing: result) == password)
{
completion(true)
}
else
{
completion(false)
}
// TODO: password is wrong,
// TODO: username is wrong
// TODO: else if timeout
}
}
catch let error as NSError {
print(error.localizedDescription)
completion(false)
}
}
else if let error = error
{
print(error.localizedDescription)
completion(false)
}
}
task.resume()
}
Rewrite code to :
let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [[String : Any]]
This is needed as your JSON response is an array of dictionaries, like the others have mentioned.
Access the result using:
let result = json.first["Password"]

Parsing JSON without Object name

Here's the usual JSON I see:
{"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]}
But I am trying to parse this format of JSON, without the object ("employees" from the example above):
[{"id":"1","company":"1","facility":"2","starttime":"1454936400","complete_time":"1454979600","scheduled_hours":"12"},{"id":"3","company":"1","facility":"2","starttime":"1455021660","complete_time":"1455061660","scheduled_hours":"12"}]
Here's the code that I'm trying to use:
let requestURL: NSURL = NSURL(string: url)!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let stations = json[1] as? [[String: AnyObject]] {
print(json)
for station in stations {
if let name = station["company"] as? String {
print(name)
}
}
}
}catch {
print("Error with Json: \(error)")
}
}
}
task.resume()
But I am not able to output any of the values from JSON data. How do I do it? I am very new in Swift and XCode.
Or if I can format my data to look like the first JSON, would it be alright? The data is being returned as an array from an SQL query.
UPDATE: When I print(json[1]) it only prints the second set. I think I'm getting closer.
NSJSONSerialization.JSONObjectWithData can be tricky because it can return either an Array aka [AnyObject] or a Dictionary aka [String: AnyObject].
Then you have to test what the result is :
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let json = jsonData as? [[String: AnyObject]] {
// json starts with an array
for value in json {
// loop through array
}
} else if let json = jsonData as? [String: AnyObject] {
// json starts with a key
for (key, value) in json {
// loop through dictionary key/values
}
} else {
// This json is broken
}
1-check that statusCode condition is true(200 or "200"?)
2-print data before try catch
if (statusCode == 200) {
print(data)
do{
......
}
3- print json object
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
print(json)
and
4-check json[1] same as [[String: AnyObject]]

How can I fetch JSON data from a PHP file using Swift 2.1 and Xcode?

I've been trying to pull data from one of my databases to display on a mobile app that I am making using swift 2.1 and Xcode. I have a mysql database that is set up and a php script running from my server that echo's JSON encoded data from that database.
My swift application can post data to the PHP script and send data to the database, but I can't get data from the PHP script to display on the application. I have tried most of the methods, but they don't seem to work for the latest version of swift.
Here is my code:
func dataOfJson(url: String) -> NSArray {
let data = NSData(contentsOfURL: NSURL(string: url)!)
let result: NSArray = []
do {
let json = try (NSJSONSerialization.JSONObjectWithData(data!, options: [NSJSONReadingOptions.MutableContainers, NSJSONReadingOptions.AllowFragments]) as? NSDictionary)
if let parseJSON = json {
let resultValue = parseJSON["id"] as? String?
print(resultValue)
}
} catch let error as NSError {
print(error.localizedDescription)
}
return result
}
And my PHP file's echoed result looks like this:
[{"id":"alex"},{"id":"jeff"},{"id":"jack"}]
How can I pull that JSON data and store it in swift variables?
Try This
func dataOfJson(url: String) -> Array<Dictionary<String,String>>? {
let data = NSData(contentsOfURL: NSURL(string: url)!)
do {
let jsonArray = try NSJSONSerialization.JSONObjectWithData(data!, options: [NSJSONReadingOptions.MutableContainers, NSJSONReadingOptions.AllowFragments]) as? Array<Dictionary<String, String>>
print("json := \(jsonArray)")
return jsonArray;
} catch let error as NSError {
print(error.localizedDescription)
return nil;
}
}
I have tested with below code, working fine.
let string = "[{\"id\":\"alex\"},{\"id\":\"jeff\"},{\"id\":\"jack\"}]";
let data = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding)
let jsonArray = try NSJSONSerialization.JSONObjectWithData(data!, options: [NSJSONReadingOptions.MutableContainers, NSJSONReadingOptions.AllowFragments]) as? Array<Dictionary<String, String>>
print("json := \(jsonArray)")
for object in jsonArray! {
print("id := \(object["id"])");
}

Categories