I'm trying to retrieve simple text data out of my database. When the app runs, you type in whatever you want and it saves it to the database. That part is working. When i log in to phpMyAdmin, that data is there. However, I'm trying to show the data as well, right above the textfield where the user inputs their text. When the app runs, there is nothing there. Here is my code for my retrieve data function. Thank you
func retrieveMessages(latestMessage:String) {
// Specify the URL of our retrieval web service
let url:NSURL = NSURL(string: "http://mypage.com/index.php")!
// Create a NSURLSession task with completion handler
let task:NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
do {
// Convert the json data into an array
let dataArray:[AnyObject] = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [AnyObject]
// Clear the messages array
self.messagesArray.removeAll(keepCapacity: false)
// Loop through each dictionary in the array
for data in dataArray {
let dictionary:[String:String] = data as! [String:String]
// Append it to our messages array
if dictionary["Text"] != nil {
self.messagesArray.append(dictionary["Text"]!)
}
}
dispatch_async(dispatch_get_main_queue()) {
// Refresh the table
self.tableView.reloadData()
}
}
catch{}
})
// Run the task
task.resume()
}
Related
I am trying to retrieve data from my own API, if i try to connect to my API using chrome browser, it gives JSON data back like this
{"id":"52","username":"aasad23","fullname":"aasad
laksana","email":"aasad#gmail.com","avatar":"/Applications/XAMPP/xamppfiles/htdocs/Twitter/Avatar/52/avatar.jpg"}
but, when I tried to access the API through my iOS app, it gives an error while doing JSON serialization, it give an error:
the data couldn’t be read because it isn’t in the correct format
what does it mean the correct format?
I have checked that the code error in this line
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
Thats why the catch error is activated and give that error message.
here is the full code of this task
URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async(execute: {
if error == nil {
do {
// json containes $returnArray from php
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
// declare new parseJSON to store json
guard let parsedJSON = json else {
print("Error while parsing")
return
}
print(parsedJSON)
// get id from $returnArray["id"] in PHP - parseJSON["id"]
let id = parsedJSON["id"]
// successfully uploaded
if id != nil {
// save user information yang berasal dari server
UserDefaults.standard.set(parsedJSON, forKey: "parsedJSON")
} else {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = parsedJSON["message"] as! String
self.showAlert(alertTitle: "opppps", alertMessage: message, actionTitle: "OK")
})
}
// JSON serialization error
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error.localizedDescription
self.showAlert(alertTitle: "Sorry", alertMessage: message, actionTitle: "OK")
})
}
// error when connecting to server
} else {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
self.showAlert(alertTitle: "oppps", alertMessage: message, actionTitle: "OK")
})
}
})
}.resume()
}
try
let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: AnyObject]
rather than
try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
I am having trouble using URLSession to access JSON data generated by a PHP file.
I am both confused about the Swift 3 syntax and the completion handlers.
So far I have:
override func viewDidLoad() {
super.viewDidLoad()
var data : NSMutableData = NSMutableData()
let urlString: String = "http://seemeclothing.xyz/service.php"
let urlObject: URL = URL(string: urlString)!
let response = URLResponse
let config = URLSessionConfiguration.default
let sessionObject: URLSession
sessionObject.dataTask(with: urlObject) { (Data?, URLResponse?, Error?) in
print(data)
print(URLResponse)
print(Error)
}
sessionObject.resume()
}
I want sessionObject to go to my server and print JSON data from PHP file.
Any help would be greatly appreciated.
I would strongly suggest using Alamofire. It abstracts away all the tedious stuff in URLSession. I switched to this a few days ago and am a happy camper since then.
For your problem:
Alamofire.request("https://httpbin.org/get").responseJSON { response in
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
I know this question has been asked dozens of times before but unfortunately I'm not knowledgable enough with Swift to adapt those answers to my issue.
Basically I have a function that sends a POST request to a php script on a server but the response seems to take longer to receive than it does for my script to utilise the result. It sends a number variable and receives one as a response so I am also converting it from an 'any_object' to an 'NSNumber'.
From what I understand I need to implement a completion handler but I can't seem to figure out how to get it to work with my code below.
var dataResult: Int = 0
var dataReceived: NSNumber?
func remoteRand() {
let dataToSend = 1
let myUrl = NSURL(string: "http://localhost/scripts/phpScript.php")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
let postString = "dataToSend =\(dataToSend)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
dispatch_async(dispatch_get_main_queue()) {
if (error != nil) {
self.displayAlertMessage((error?.localizedDescription)!)
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
if let parseJSON = json {
let dataReceived = parseJSON["dataValue"]
self.dataResult = (dataReceived as! NSNumber).integerValue
print("\(self.dataResult) is server response")
}
} catch { print(error)}
}
}
task.resume()
processResult()
}
func processResult() {
print(dataResult)
}
The result I get is:
0
1 is server response
How do I either make it wait for the response before proceeding to the next function or trigger the next function once completion is confirmed?
Thanks in advance!
The task completes on a different thread than which it is called, this is by design so network requests don't stop execution on the main thread. So your block of code is sent off async and processResult is called before the network request is finished. You can put the call in the do block or add a closure to the method that can be called.
func remoteRand(completion: (response: Int) ->()) {
// your code
// process JSON
// get value
completion(dataReceived)
// is passed back, just like the dataTaskWithRequest method to your caller where you can set the property on self, etc.
}
using it somewhere:
remoteRand { [weak self] (response) in
self?.dataResult = response
}
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"])");
}
I am having some difficulty with an asynchronous data fetch from a server (MySQL database which I access through some PHP web services). My code is below:
func RetreiveStaff() {
SetProgramMode()
self.astrUsers = [String]()
self.pkvUser.reloadAllComponents()
if self.booCurrentDataVersion == true {
var url:NSURL = NSURL(string: "http://www.website.com.au/retrievestaff.php")!
let task:NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in
if error == nil {
let dataArray:[AnyObject] = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! [AnyObject]
for data in dataArray {
let dictionary:[String:String] = data as! [String:String]
if dictionary["StaffID"] != nil {
self.astrUsers.append(dictionary["LastName"]! + ", " + dictionary["FirstName"]!)
self.astrUserIDs.append(dictionary["StaffID"]!)
self.pkvUser.reloadAllComponents()
}
self.pkvUser.reloadAllComponents()
}
} else {
let actionSheet:UIAlertController = UIAlertController(title: "Connection Error", message: "\(strAppName) was unable to load data. Check you are connected to the internet and restart the app.", preferredStyle: UIAlertControllerStyle.Alert)
let firstAlertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: {
(alertAction:UIAlertAction!) in
})
actionSheet.addAction(firstAlertAction)
self.presentViewController(actionSheet, animated: true, completion: nil)
}
})
task.resume()
}
}
When the code executes, the data is fetched as it should, but the view doesn't display it. Basically, as you can see, I grab the data, put it in an array and then reload my pickerView (which uses the array as its datasource). The pickerView remains visibly empty for about 20 seconds after the code is executed, and then suddenly appears. However, if the user taps on, drags, changes the value of, etc. the pickerView during the 20 seconds, the data appears.
From my understanding of the problem, this means that the data is being fetched and put into the pickerView but the view isn't reloading correctly, despite my numerous and probably excessive number of self.pkvUser.reloadAllComponents().
What am I doing wrong?
(I have also checked out these questions but they haven't solved the issue:
Swift: Asynchronous callback
Asynchronous Fetching Swift Xcode
iOS Swift: Displaying asynchronous data on a TableView )
displaying any view in IOS should ALWAYS be in the main thread.
when you are doing async requests, push the results to the user's view from main thread like this:
var someView : UIView = someAsyncCallBack..
dispatch_async(dispatch_get_main_queue()) {
currentView.addSubview(someView);
}
try this code, after the async request is done, there's no problem to handle the response in the main queue, this also solves the display lag
if error == nil {
dispatch_async(dispatch_get_main_queue()) {
let dataArray:[AnyObject] = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! [AnyObject]
for data in dataArray {
let dictionary:[String:String] = data as! [String:String]
if dictionary["StaffID"] != nil {
self.astrUsers.append(dictionary["LastName"]! + ", " + dictionary["FirstName"]!)
self.astrUserIDs.append(dictionary["StaffID"]!)
self.pkvUser.reloadAllComponents()
}
self.pkvUser.reloadAllComponents()
}
}
}