Get value from JSON file in Swift - json

I have a JSON file which i converted to a NSDictionary object. My question is how do i get one single value out from this object? I make a httppost to my webside and then i get an JSON array back with to values "success" and "userId" i want to check on the success if it is true or false.
import UIKit
class ViewController2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func HttpBtn(sender: AnyObject) {
PostToServer()
HttpPost()
}
func PostToServer()
{
println("Button Presed")
}
func HttpPost()
{
var postString = "email=joakim#and.dk&password=123456"
//Declare URL
var url: NSURL! = NSURL(string: "http://95.85.53.176/nhi/api/app/login")
var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
//Declare which HTTPMethod
request.HTTPMethod = "POST"
//POST data
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
data, response, error in
if error != nil
{
println("error=\(error)")
return
}
println("response =\(response)")
var responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("responseString =\(responseString)")
var error: NSError?
var myJSON = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &error) as? NSDictionary
println(myJSON)
}
task.resume()
}
}
output
responseString =Optional({"success":true,"userId":"62"})
Optional({
success = 1;
userId = 62;
})

You can access using its key value like
var success = myJSON["success"]!.intValue
var userId = myJSON["userId"]!.intValue
if(success == 1) //if true
{
//Do something
}
Same with userId

Related

why is my json returning nil

let myUrl = URL(string: "http://app.avatejaratsaba1.com/api/Values/GetPriceList?paymentType=1&goodType=102")
var request = URLRequest(url: myUrl!)
request.httpMethod = "GET" // compose a query string
request.addValue("application/json", forHTTPHeaderField: "content-type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request)
{
(data : Data? , response : URLResponse? , error : Error?) in
self.removeActivtyIndicator(activityIndicator: MyActivityIndicator)
if error != nil
{
self.DisplayMessage(UserMessage: "2Could not successfully perform this request , please try again later.")
print("error = \(String(describing : error))")
}
// let's convert response sent from a server side code to a NSDictionary object:
do { let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json
{
I have the exact code in another viewcontroller with another url and it works properly !!! it works properly in Postman!!
and i'm coding swift
UPDATED::::
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [[String:Any]] {
var goodNameArray = [String].self
for i in 0..<json.count{
guard let goodName = json[i]["goodName"] as? String else{return}
Global.GlobalVariable.GoodName = goodNameArray.append(goodName)
}
print("GoodNames: \(goodNameArray)")
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("raw response: \(String(describing: responseString))")
}
}
task.resume()
and the error it returns is :
Cannot invoke 'append' with an argument list of type '(String)'
global var code:::::
class Global: UIViewController
{
struct GlobalVariable
{
static var companyName = "Company"
static var bigName = ((0) , (""))
static var names = ["Loading..." , ""]
////////////
static var AgentInfo = "agentinfo"
////////////
static var genaral_goodID = 000
static var GoodName = [String]()
static var PriceVariableName = "PriceVariableName"
static var paymentType = "paymentType"
static var fee = "fee"
static var exipreDate = "exipreDate"
static var expireTime = "expireTime"
}
}
UPDATED::::::
uitable
class secondtable : TableViewController
{
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Global.GlobalVariable.names.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let content = Global.GlobalVariable.GoodName[indexPath.row]
cell.textLabel?.text = content
//cell.accessoryType = .disclosureIndicator
return cell
}
}
here in this par of my code , i'm supposed to populate a table with "goodName"
I tested in bellow way ,it is working for me.The response in array of dictionaries. Don't do force unwrap.
func viewDidLoad(){
downloadDataFromServer { (success, goodNamesArray) in
if success{
print("goodNamesArray: \(goodNamesArray)")
print("successfully updated tableview data")
self.tableView.reloadData()
}
}
}
func downloadDataFromServer(completionHandler: #escaping(Bool,[String])->()){
guard let url = URL(string: "http://app.avatejaratsaba1.com/api/Values/GetPriceList?paymentType=1&goodType=102") else {
return
}
let request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print("request failed \(String(describing: error))")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [[String:Any]] {
var goodNameArray = [String]()
for i in 0..<json.count{
guard let goodName = json[i]["goodName"] as? String else{return}
self.goodNameArray.append(goodName)
}
print("GoodNames: \(self.goodNameArray)")
Global.GlobalVariable.GoodName = goodNameArray
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("raw response: \(String(describing: responseString))")
}
}
task.resume()
}
Do yourself a favour and save some time by reading up on the Codable protocol. It will allow you to generate a pretty decent JSON-parser by basically just defining your structure. Using JSONDecoder.decode will provide you with much more valuable error information if something goes wrong.
Since your API is currently only providing an empty array using the URL you provide us with it is pretty hard to come up with any meaningful code. You should resort to a simple String-representation of your JSON, at least a minimalized form that shows us all about the structure. That way your question would not depend on the workings of a probably fairly complicated web service.

Xcode func used in another View Controller

I have this func in a Swift file, and it returns the value of the data in the database and prints it out in the counsel.
I want to use the value in the other View Controller but I can't get this to work, so I hope somebody can help me.
It is the nameUser, statusUser and pointUser I like to use in other View Controller.
import Foundation
import UIKit
var code = "100"
var getStatusUSer = ""
class getJSON: NSObject, URLSessionDataDelegate
{
//properties
var data : NSMutableData = NSMutableData()
func downloadItems()
{
let url = NSMutableURLRequest(url: NSURL(string: "http://www.hholm.dk/time_app/qrcode4.php")! as URL)
url.httpMethod = "POST"
let postString = "username=\(code)"
url.httpBody = postString.data(using: String.Encoding.utf8)
print(url.httpBody = postString.data(using: String.Encoding.utf8))
var session: URLSession!
let configuration = URLSessionConfiguration.default
session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url as URLRequest)
task.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
self.data.append(data as Data);
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
if error != nil
{
print("Not Found", error)
}
else
{
print("Ok")
self.parseJSON()
}
}
func parseJSON()
{
var jsonResult: NSArray = NSArray()
do
{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
print("jsonResult.count",jsonResult.count)
}
catch let error as NSError
{
print("jsonResult: ", error)
}
var jsonElement: NSDictionary = NSDictionary()
var contador = 0
for i in (0..<jsonResult.count)
{
jsonElement = jsonResult[i] as! NSDictionary
if let nameUser = jsonElement["name"] as? String,
let pointUser = jsonElement["point"] as? String,
let statusUser = jsonElement["status"] as? String
{
getStatusUSer = statusUser
print("Name: ", nameUser)
print("Status: ", statusUser)
print("Point: ", pointUser)
}
}
}
}
Hi Woof this is what i have in my viewcontroler:
import UIKit
class inputcodeViewController: UIViewController {
#IBOutlet weak var input: UITextField!
#IBAction func but(_ sender: Any) {
downloadItems()
}
func downloadItems(){
let getJson = GetJSON()
//setting the delegate
getJson.delegate = self
//starting download
getJson.downloadItems()
}
}
extension inputcodeViewController: GetJSONDelegate {
func didReceiveValues(name: String, status: String, point: String){
//now you can use values in your view controller
}
}
how can i print the values
You can use protocol to return those values:
import Foundation
import UIKit
var code = "100"
var getStatusUSer = ""
//define the protocol
protocol GetJSONDelegate {
func didReceiveValues(name: String, status: String, point: String)
}
//I've changed the first char of the class name to uppercase
class GetJSON: NSObject, URLSessionDataDelegate{
//properties
var data : NSMutableData = NSMutableData()
//delegate
var delegate: GetJSONDelegate?
func downloadItems(){
let url = NSMutableURLRequest(url: NSURL(string: "http://www.hholm.dk/time_app/qrcode4.php")! as URL)
url.httpMethod = "POST"
let postString = "username=\(code)"
url.httpBody = postString.data(using: String.Encoding.utf8)
print(url.httpBody = postString.data(using: String.Encoding.utf8))
var session: URLSession!
let configuration = URLSessionConfiguration.default
session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url as URLRequest)
task.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
self.data.append(data as Data);
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
if error != nil
{
print("Not Found", error)
}
else
{
print("Ok")
self.parseJSON()
}
}
func parseJSON()
{
var jsonResult: NSArray = NSArray()
do
{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
print("jsonResult.count",jsonResult.count)
}
catch let error as NSError
{
print("jsonResult: ", error)
}
var jsonElement: NSDictionary = NSDictionary()
var contador = 0
for i in (0..<jsonResult.count)
{
jsonElement = jsonResult[i] as! NSDictionary
if let nameUser = jsonElement["name"] as? String,
let pointUser = jsonElement["point"] as? String,
let statusUser = jsonElement["status"] as? String
{
getStatusUSer = statusUser
print("Name: ", nameUser)
print("Status: ", statusUser)
print("Point: ", pointUser)
//here we will return received data to the delegate
self.delegate?.didReceiveValues(name: nameUser, status: statusUser, point: pointUser)
}
}
}
}
Now we need to set your controller as a delegate for that protocol:
//this is an example, you need to add the methods described in your controller where you want to use those values
class YourViewController: UIViewController{
// the method that is called by you to get values
func downloadItems(){
let getJson = GetJSON()
//setting the delegate
getJson.delegate = self
//starting download
getJson.downloadItems()
}
}
//defining protocol methods in the extension of the view controller
extension YourViewController: GetJSONDelegate {
func didReceiveValues(name: String, status: String, point: String){
//now you can use values in your view controller
}
}

json data not getting loaded into UITextView in swift

class ViewController:ViewController,UITextViewDelegate{
#IBOutlet weak var newTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
newTextView.delegate = self
dataFun()
}
func dataFun()
{
let url : String = "http:xyz/abc"
let request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
print("Start")
let session = NSURLSession.sharedSession()
session.dataTaskWithRequest(request) { (data, response, error) -> Void in
do {
let jsonResult: NSDictionary! = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers) as? NSDictionary
print("In method\(jsonResult)")
// let data = jsonResult["description"]
// print(data!)
if (jsonResult != nil)
{
// process jsonResult
print("Data added")
let test:String = jsonResult["description"] as! String
print(test)
self.newTextView.text = test
} else {
print("No Data")
// couldn't load JSON, look at error
}
}
catch {
print("Error Occured")
}
}
.resume()
}
In my app I am going to call services from API
I can see my json data in console.
that data is not show in textviewController
it shows fatal error:
unexpectedly found nil while unwrapping an Optional value
and then crash the app
Make sure #IBOutlet weak var newTextView: UITextView! is set up correctly.
Make sure let test:String = jsonResult["description"] as! String doesn't crash. JSON has field description and it's a string.

swift do task after the preview task is finished

In my swift 2 app i would like to make an http-post-request to get data of my mysql database. After that I would like to write this data into my core data.
I have the code part for request and write.
How do I get the following structure.
Request Data
if request data complete write in into core data
Could this be the correct thing?
This is my SyncMYSQL function in my Sync.swift file.
class func SyncMYSQL() {
print("START SYNC MYSQL")
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let defaults = NSUserDefaults.standardUserDefaults()
let request = NSMutableURLRequest(URL: NSURL(string: "https://xxx")!)
request.HTTPMethod = "POST"
let postString = "userid=12"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// if no internet connection
guard error == nil && data != nil else {
print("error=\(error)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
let fetchRequest = NSFetchRequest(entityName: "ITEMS")
fetchRequest.returnsObjectsAsFaults = false
do {
let results = try managedObjectContext!.executeFetchRequest(fetchRequest)
for managedObject in results {
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedObjectContext!.deleteObject(managedObjectData)
}
} catch let error as NSError {
print("Detele all data in ITEMS error : \(error) \(error.userInfo)")
}
var x = 0
while (x < responseString.count ) {
let newItem = NSEntityDescription.insertNewObjectForEntityForName("ITEMS", inManagedObjectContext: managedObjectContext!) as! CoreData_ITEMS
newItem.name = responseString[x]
x++
}
dispatch_sync(dispatch_get_main_queue(),{
print("FINISH MYSQL")
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
});
}
task.resume()
}
This function i call from my view controller like this way:
func RequestData() {
Sync.SyncMYSQL()
print ("Start Core Data")
let fetchRequest = NSFetchRequest(entityName: "ITEMS")
do {
try data = managedObjectContext!.executeFetchRequest(fetchRequest) as! [CoreData_ITEMS]
} catch { }
Table.reloadData()
}
You should use closure blocks as callback when the operation ends
class func SyncMYSQL(onSuccess: ()->()){
// your custom events
// your custom events
// your custom events
if MYSQLisSynced == true {
// when MYSQL is synced you can call the success block
onSuccess()
}
}
In other file when you call the function SyncMYSQL() you have to specify the on success block
SyncMYSQL { () -> () in
//custom callback actions
}

Return NSURLSession response to its calling function

I have written two following functions for using NSURLSession.
func getStringFromRequest(completionHandler:(success:Bool, data: NSData?) -> Void) {
let prefs = NSUserDefaults.standardUserDefaults()
var conn_timeout = prefs.stringForKey("conn_timeout")!
var IP = prefs.stringForKey("IP")!
var port = prefs.stringForKey("Port")!
prefs.synchronize()
var request = NSMutableURLRequest(URL: NSURL(string: "http://\(IP):\(port)/")!)
var response: NSURLResponse?
var error: NSError?
var jsonString = ["osname":"iOS","mobile_manufacturer" : "Apple","mobile_model" : "iPhone Simulator","osversion" : "8.4"] as Dictionary<String, String>
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(jsonString, options: nil, error: &error)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("gzip", forHTTPHeaderField: "Accept-encoding")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
if let unwrappedError = error {
print("error=\(unwrappedError)")
}
else {
if let unwrappedData = data {
completionHandler(success: true, data: unwrappedData)
return
}
}
completionHandler(success: false, data: nil)
}
task.resume()
}
func performPost() -> NSDictionary {
var result = NSDictionary()
getStringFromRequest { (success, data) -> Void in
if (success) {
if let unwrappedData = data {
if let responseString = NSString(data: unwrappedData, encoding: NSUTF8StringEncoding) {
println("------------------>>>>>>NSURLSession>>>>>>>-------------------------->\n: \(responseString)")
result = (NSJSONSerialization.JSONObjectWithData(unwrappedData, options: NSJSONReadingOptions.allZeros, error: nil) as? NSDictionary)!
}
}
}
else {
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Failed>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
}
}
}
I am calling the performPost function as follows:
self.connectionHelper.performPost()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { ()->() in
println("self.connectionHelper.result>>>>>>========================================>>>>>>> : \(self.connectionHelper.result)!")
})
Output is as follow:
self.connectionHelper.result>>>>>>========================================>>>>>>> : {
}!
------------------>>>>>>NSURLSession>>>>>>>-------------------------->
After looking at the output of the performPost function I can say that the execution to the pritln function first but it is called later than performPost.
How can I set the value of result first in the performPost function then prints its value after completion of the performPost function.
Can it be possible?
Instead of calling dispatch_async to print the results, pass a completion handler block to your performPost method, and print the results in that completion handler block.