iOS swift 3 xcode 8 parsingJson doesn't reflects into database - ios

I have been trying to insert certain data into mysql through php. But however i am getting an error coded 3840.Below is the code i am working on:-
#IBAction func btnVerify(_ sender: Any) {
let myUrl = URL(string: "http://kumbhkaran.co.in/ios_otp_check/verifyOTP.php");
var request = URLRequest(url:myUrl!);
request.httpMethod = "POST";
let postString = "category=\(Category)&subcategory=\(SubCategory)&vendorname=\(ShopName)&managername=\(ManagerName)&managercontact=\(ManagerMobile)&mobile=\(UserName)&landline=\(Landline)&email=\(Email)&website=\(Website)&city=\(City)&address=\(Address)&area=\(Area)&pincode=\(Pincode)&rentowned=\(ShopStatus)&homedelivary=\(HomeDelivery)&pwd=\(Password)&marketing_ref=\(MarketingRef)&Working_Start_time=\(StartTime)&Working_End_time=\(EndTime)"
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
//spinningActivity!.hide(true)
if error != nil {
self.displayAlertMessage(messageToDisplay: error!.localizedDescription)
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
let userId = parseJSON["message"] as? String
if( userId != nil)
{
let myAlert = UIAlertController(title: "Alert", message: "Registration successful", preferredStyle: UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default){(action) in
self.dismiss(animated: true, completion: nil)
}
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil)
} else {
let errorMessage = parseJSON["message"] as? String
if(errorMessage != nil)
{
self.displayAlertMessage(messageToDisplay: errorMessage!)
}
}
}
} catch{
print(error)
}
}
}
task.resume()
}
However after all this code i get an error stated as below:-
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start
with array or object and option to allow fragments not set."
UserInfo={NSDebugDescription=JSON text did not start with array or
object and option to allow fragments not set

Try this :
Set option value to allowFragments instead of mutableContainers.
Probably the json response is not properly formed.
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary

Related

Unable to Json response is not working

Swift 3.0 (Xcode 8.3)
I'm trying to make a small program, that send a username to a web data base. I have found out how to send first_name, last_name,dob,owner_mobile,owner_email,
owner_password,choice_for_verification, by using in POST method. I obtain a JSON string earlier, then when I try to parse it, I get the above error on the try NSJSONSerialization line, on the as keyword. What did I do wrong? Thanks for your answers.
#IBAction func Login_Action(_ sender: Any)
{
var responseString : String!
var request = URLRequest(url: URL(string: "http://dev.justpick2go.com/cpanel/api/owner/ownerregistration.php")!)
request.setValue("Application/x-www.ownerregistration.php.com", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "first_name=\(txtFirstName.text!)&last_name=\(txtLastName.text!)&dob=\(txtDOB.text!)&owner_mobile=\(txtMobileNo.text!)&owner_email=\(txtEmailID.text!)&owner_password=\(txtPassword.text!)" //&choice_for_verification=\(email)" // sending a parameters
print("\(postString)")
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error != nil else { //checking for fundamental error
print("Error is =\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200
{ // checking for http errors
print("statusCode should be 200 , but is\(httpStatus.statusCode)")
print("response is =\(String(describing: response))")
}
responseString = String(data: data, encoding: .utf8)
print("ResponseString=\(responseString!)")
do {
let json : NSDictionary! = try! JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSDictionary
self.parseTheJSonData(JsonData: json)
}
catch
{
print(error)
}
}
task.resume()
}
func parseTheJSonData(JsonData : NSDictionary)
{
var successMessage : String = String()
var sampleCode : Int = Int()
let verificationAlert = UIAlertController()
if ((JsonData.value(forKey: "success") as! Int) == 1)
{
successMessage = "Login is Successful"
sampleCode = JsonData.value(forKey: "success") as! Int
verificationAlert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))
verificationAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (Relogin) in
let Log = self.storyboard?.instantiateViewController(withIdentifier: "") as! LoginViewController
self.navigationController?.pushViewController(Log, animated: true)
self.present(Log, animated: true, completion: nil)
}))
}
else if ((JsonData.value(forKey: "success") as! Int) == 0)
{
sampleCode = JsonData.value(forKey: "success") as! Int
successMessage = "Please try again"
verificationAlert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
}
verificationAlert.title = successMessage
OperationQueue.main.addOperation
{
self.present(verificationAlert, animated: true, completion: nil)
}
}

Filter string from JSON from asp.net web api using swift 3

I am new to web development and Swift
I created a web api based on ASP.NET and I connected my ios app so I can do GET, POST, PUT, DELETE.
When I send GET request with specific ID number
I get output in Xcode as following:
Data:
Optional("{\"Id\":1,\"UserName\":\"codeinflash\",\"UserPassword\":\"Wldnrodxxxx\",\"UserEmail\":\"codeinflash#gmail.com\",\"Rebate\":0.00,\"MemCom\":123.44}")
Here is function in Swift:
//GET /api/account/{id}
#IBAction func GetAccount(_ sender: Any) {
let _accountIdNumber = AccountIdNumber.text
if (_accountIdNumber!.isEmpty){
createAlert(title: "Warning", message: "Account ID # is required")
return
}
let restEndPoinst: String = "http://tresmorewebapi2.azurewebsites.net/api/account/" + _accountIdNumber!;
guard let url = URL(string: restEndPoinst) else {
print("Error creating URL")
return
}
var urlRequest = URLRequest(url: url)
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
// api key need urlRequest.setValue(<#T##value: String?##String?#>, forHTTPHeaderField: "APIKey")
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
var userEmail = ""
var rebate = ""
var memcom = ""
let task = session.dataTask(with: urlRequest, completionHandler:
{
(data, response, error) in
print("Error:")
print(error)
print("response:")
print(response)
print("Data:")
print(String(data: data!, encoding: String.Encoding.utf8))
//////////////I think I need logic here to filter the data
userEmail = data.substring of find emailaddress
rebate = data.substring find users' rebate
memcom = same logic
then show alert window with his info and I will show his info on next page which is a Dashboard page view
})
task.resume()
}
Honestly I am not sure the Data is JSON data but the output in Xcode is in string.
My purpose is get uer's data and store in local variables that passes them to next view(Dashboard) in ios Swift.
Thank you!
Added
Here is the task getting data from web api in login fuction swift
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
var userEmail = ""
var rebate = ""
var memcom = ""
let task = session.dataTask(with: urlRequest, completionHandler:
{
(data: Data?, response: URLResponse?, error: Error?) in
print("Error:")
print(error)
print("response:")
print(response)
print("Data:")
print(String(data: data!, encoding: String.Encoding.utf8))
let json = try? JSONSerialization.jsonObject(with: data!) as! [String: AnyObject] ?? [:];
userEmail = json?["UserEmail"] as? String ?? ""
createAlert(title: "Got User Eamil Address!", message: userEmail)
})
task.resume()
But I get nothing in my alert view. The alert view working fine I tested.
Here is my createAlert fuction in Swift
func createAlert(title:String, message:String){
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (anction) in
alert.dismiss(animated: true, completion: nil)}))
self.present(alert, animated: true, completion: nil)
}
You have answer in comments already, but this is less "swifty" way, more readable for someone new to Swift (pay attention and try to understand what is going on and how you can make this more compact):
do {
guard let unwrappedData = data else{
//data is nil - handle case here
return //exit scope
}
guard let dictionary = try JSONSerialization.jsonObject(with: unwrappedData) as? [String:AnyObject] else {
//you cannot cast this json object to dictionary - handle case here
return //exit scope
}
userEmail = dictionary["UserEmail"]
DispatchQueue.main.async { [weak self] in
self?.createAlert(title: "Got User Eamil Address!", message: userEmail)
}
} catch _ {
//handle error
}

IOS Swift - go to another view after getting stats from NURLSESSION

Once the user click the login button, i will call the func LoginClicked and get the status from api:
func LoginClicked(sender: AnyObject)
{
data_request{
(response) -> () in
let arrResponse = response.componentsSeparatedByString("|")
if (arrResponse[2] == "1"){
self.performSegueWithIdentifier("Login", sender: self)
}
else {
let alert = UIAlertController(title: "Login Failed", message: "Invalid Login!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
func data_request(completion : (response:NSString) -> ()){
let txtUI : String = txtUsername!.text!
let txtPWD : String = txtPassword!.text!
let url = NSURL(string: "http://myweb.net/?UI=\(txtUI)&PW=\(txtPWD)")!
let request = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(request, completionHandler: {
(
let data, let response, let error) in
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
print("error")
return
}
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
completion(response : dataString!)
})
task.resume()
}
If success, it will move to another view. Otherwise, show failed alert. it will hit the error BAD_EXECUTION_INSTRUCTION when calling self. in both condition.
After get the hint from #Tj3n, it can do the proper action now.
func data_request(completion : (response:NSString) -> ()){
let txtUI : String = txtUsername!.text!
let txtPWD : String = txtPassword!.text!
let url = NSURL(string: "http://myweb.net/?UI=\(txtUI)&PW=\(txtPWD)")!
let request = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(request, completionHandler: {
(
let data, let response, let error) in
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
print("error")
return
}
dispatch_async(dispatch_get_main_queue(), {
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
//let response = dataString?.componentsSeparatedByString("|")
//print(dataString)
//print(response![2])
let arrResponse = dataString!.componentsSeparatedByString("|")
if (arrResponse[2] == "1"){
self.performSegueWithIdentifier("Login", sender: self)
}
else {
let alert = UIAlertController(title: "Login Failed", message: "Invalid Login!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
})
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
completion(response : dataString!)
})
task.resume()
}

Calling a func in other swift file which works with web-service returns nothing

In swift 2 When I'm communicating with a web-service and when I write these codes in button action it works fine.
let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: .Alert)
let ok = UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in })
alert.addAction(ok);
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.myaddress.com/web-service/iostest.aspx")!)
request.HTTPMethod = "POST"
var postString = String();
postString = "uid=1";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard error == nil && data != nil else {
alert.title="Error"
alert.message = "Connection error"
dispatch_async(dispatch_get_main_queue()){
self.presentViewController(alert, animated: true, completion: nil)
}
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
alert.title="Error"
alert.message = "Server error"
dispatch_async(dispatch_get_main_queue()){
self.presentViewController(alert, animated: true, completion: nil)
}
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
alert.title="Info"
alert.message = responseString as? String
dispatch_async(dispatch_get_main_queue()){
self.presentViewController(alert, animated: true, completion: nil)
}
}
task.resume()
As I said this works fine but as I want to do this from different ViewControls as well I have created a swift file which contains a struct and a static func in that struct that returns the the "responseString" so I could alert it in the view control. Something like this:
struct globalClass {
static func sendInfo(url: String, data: String) -> (answer: String, errorCode: Int32) {
var res = String();
var err = Int32();
err = 0;
let request = NSMutableURLRequest(URL: NSURL(string: url)!);
request.HTTPMethod = "POST";
let postString: String = data;
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard error == nil && data != nil else {
err = 1;
return;
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
err = 2;
return;
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding);
res = (responseString as? String)!;
}
task.resume();
return (res, err);
}
But now when I call this func from my button it shows me an empty alert very fast that it seems like it didn't get anything from web-service and didn't even try too.
I put these in the button action:
#IBAction func btnData(sender: AnyObject) {
let y: String = "uid=1";
let res = globalClass.sendInfo("http://www.myaddress.com/web-service/iostest.aspx", data: y);
let alert = UIAlertController(title: "", message: "", preferredStyle: .Alert);
let OK = UIAlertAction(title: "OK", style: .Default, handler: nil);
alert.addAction(OK);
if (res.errorCode==0) {
alert.title = "Info";
alert.message = res.answer;
} else if (res.errorCode==1) {
alert.title = "Error";
alert.message = "Error connecting to server";
} else {
alert.title = "Error";
alert.message = "Server returned an error";
}
dispatch_async(dispatch_get_main_queue()){
self.presentViewController(alert, animated: true, completion: nil);
};
}
Thanks for the help,
Afshin Mobayen Khiabani
globalClass.sendInfo uses async call - dataTaskWithRequest. The result of the request will be delivered in completion of this method. But you don't wait for that result, instead you try to use sendInfo like a sync function.
To be able to deliver the result from dataTaskWithRequest's completion, put your own completion into sendInfo and invoke this completion (closure) when the result is delivered. An example
struct GlobalClass {
static func sendInfo(url: String, data: String, completion: (answer: String?, errorCode: Int32?) -> Void) {
// you code here which prepares request
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
// you parse the result here
// you deliver the result using closure
completion(string, error)
}
task.resume();
}
}
And an example of usage:
func usage() {
GlobalClass.sendInfo("url", data: "data") { (answer, errorCode) in
// your answer and errorCode here
// handle the result
}
}
static func sendInfo(url: String, data: String, completion: (answer: String, errorCode: Int32) -> ()){
//Your code..
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding);
res = (responseString as? String)!;
completion(answer: res, errorCode: err)
}
task.resume()
}
Then when you call the sendInfo, call like so:
sendInfo(url: "your url", data: "your data") { (result, error) in
//you use your result and error values as u want.
}

Swift, unable to read data in url

I ran this and nothing happens when I try to send the data. So I debugged this and the it can't read anything from the url. It says "unable to read data". I checked the url its correct, I checked this sever its good and my php code. I experience this problem only when I upgraded to swift 2 or Xcode7. Thanks for the help!
let myUrl = NSURL(string: "http://localhost/SwiftAppAndMySQL/scripts/registerUser.php");
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "POST";
let postString = "userEmail=\(userEmail!)&userFirstName=\(userFirstName!)&userLastName=\(userLastName!)&userPassword=\(userPassword!)";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
dispatch_async(dispatch_get_main_queue())
{
//spinningActivity.hide(true)
if error != nil {
self.displayAlertMessage(error!.localizedDescription)
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
if let parseJSON = json {
let userId = parseJSON["userId"] as? String
if( userId != nil)
{
let myAlert = UIAlertController(title: "Alert", message: "Registration successful", preferredStyle: UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default){(action) in
self.dismissViewControllerAnimated(true, completion: nil)
}
myAlert.addAction(okAction);
self.presentViewController(myAlert, animated: true, completion: nil)
} else {
let errorMessage = parseJSON["message"] as? String
if(errorMessage != nil)
{
self.displayAlertMessage(errorMessage!)
}
}
}
} catch{
print(error)
}
}
}).resume()
I experience this problem only when I upgraded to swift 2 or Xcode7.
Xcode 7 contains iOS Simulator with iOS 9. iOS 9 has a new feature – App Transport Security (ATS), which prevents non-secured connections (http). More information:
App Transport Security Technote
How to allow http-connections with ATS
I show you my example of work with JSON
let mainString = "http://api.mymemory.translated.net/get?q=\(sendWord)&langpair=\(langpair)".stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLFragmentAllowedCharacterSet())!
Alamofire.request(.POST, mainString).responseJSON { (response) -> Void in
let mainDictionary = response.result.value as! [String : AnyObject]
print(mainDictionary)
let arrayDictionary = mainDictionary["matches"] as! [AnyObject]
let matchesDictionary = arrayDictionary[0] as! [String : AnyObject]
let segment = matchesDictionary["segment"] as! String
print(segment)
let translation = matchesDictionary["translation"] as! String
print(translation)
The second example
let url = NSURL(string: "http://api.mymemory.translated.net/get?q=Hello%20World!&langpair=en%7Cit")!
let dataData = NSData(contentsOfURL: url)!
let main = try! NSJSONSerialization.JSONObjectWithData(dataData, options: NSJSONReadingOptions.AllowFragments)
print(main)

Resources