I have a problem loading json data Swift4 when its not found, why? - uitableview

When my script asks the server to load data and receives the required data everything goes well but when it fails to find the required data I can not do something in else.
func myJSON(sec:Int) {
var request = URLRequest(url: URL(string: "https://xx.com/index.php")!)
let postString = "sec=\(sec)"
request.httpMethod = "POST"
request.httpBody = postString.data(using: .utf8)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if error == nil, let data = data {
do {
if let jsonData = try JSONSerialization.jsonObject(with: data, options: []) as? [[String:String]] {
for item in jsonData {
if let sec = item["sec"] {
self.myArray_sec.append(sec)
DispatchQueue.main.async {
self.myTable!.reloadData()
//It is happening here and things are going well
self.myTable!.tableFooterView?.isHidden = true
}
}else if let error = item["error"]{
DispatchQueue.main.async {
print("error: ",error)
//But here it cannot be done
self.myTable!.tableFooterView?.isHidden = true
}
}
}
}
} catch let error as NSError {
print("error: ",error)
}
}
}
task.resume()
}
Printing error: no Data
PHP Code works
$result = mysqli_query($con,"SELECT * FROM `myTable` WHERE `sec`='".$_POST['sec']."';");
while($data = mysqli_fetch_assoc($result)) {
$rows[] = $data;
}
if ($rows[0]['sec'] != "") {
print json_encode($rows);
}
else {
print '[{"error":"no Data"}]';
}

The problem was resolved by a timer
}else if let error = item["error"]{
DispatchQueue.main.async {
print("error: ",error)
let myTimer = Timer.scheduledTimer(timeInterval: 2,
target: self,
selector: #selector(self.refresh),
userInfo: nil,
repeats: false)
}
}
#objc func refresh() {
self.myTable!.tableFooterView?.isHidden = true
}

Related

How to pause programmatic execution inside a DispatchQueue without using sleep()

so I make a post request to a server. In the response, I run some code in the main thread and conditionally call another post request. My problem is this--I need to wait ~5 seconds before the conditional is processed. How can I do this without using sleep()? (Using sleep freezes my app).
func getStuff() {
let server = appState.server + "extension"
let package = self.myID
guard let url = URL(string: server) else { return }
var urlRequest = URLRequest(url: url)
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
urlRequest.httpMethod = "POST"
guard let data = try? JSONEncoder().encode(package) else { return }
urlRequest.httpBody = data
let task = URLSession.shared.dataTask(with: urlRequest) {
(data, response, error) in
if let error = error {
return
}
guard let data = data else { return }
guard let dataString = String(data: data, encoding: String.Encoding.utf8) else { return }
let jsonData = Data(dataString.utf8)
var decodedJob: Job? = nil
do {
decodedJob = try JSONDecoder().decode(Formatter.self, from: jsonData)
} catch {
print(error.localizedDescription)
}
DispatchQueue.main.async {
self.firstTimeLoading = false
sleep(5) //how do I replicate this behavior without freezing the app?
if array == [] {
otherPostFunction()
}
}
}
task.resume()
}
Do the following:
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(5)) {[weak self] in
if self?.array ?? [] == [] {
self?.otherPostFunction()
}
}

swift with Uploading Data to a Website not working

I want to post the token to the server, but the code I wrote does not work. Post processing is not occurring. why ? Even null value does not go to server . why ?
Token is global variable(string) and iself token id.
For example: dchksjdjfs-123anksndjd
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(counterFunc), userInfo: nil, repeats: true)
}
#objc func counterFunc() {
guard let uploadData = try? JSONEncoder().encode(Tokeen) else {
return
}
let url = URL(string: "https://...../....php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
print ("uploadData: \(uploadData)")// is empty
let task = URLSession.shared.uploadTask(with: request, from: uploadData) { data, response, error in
if let error = error {
print ("error: \(error)")
return
}
guard let response = response as? HTTPURLResponse,
(200...299).contains(response.statusCode) else {
print ("server error")
return
}
if let mimeType = response.mimeType,
mimeType == "application/json",
let data = data,
let dataString = String(data: data, encoding: .utf8) {
print ("got data: \(dataString)")
}
}
task.resume()
}

calling a web service with httpMethod (POST) in swift 4.1

Let me describe view controller (page design) first. I have added one button and one label. And a function is created by me for the button. Here is the ViewController.swift file:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btnHitWebService: UIButton!
#IBOutlet weak var lblResult: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnHitWebServiceClick(_ sender: Any) {
if (getTokenWithPostMethod() == true)
{
lblResult.text = "yes, we get token: " + g_token
}
else
{
lblResult.text = "there is an error, please try again later"
}
}
func getTokenWithPostMethod() -> Bool{
var funcResult = false
var request = URLRequest(url: URL(string: "https://apiABCDEFG.com/token")!)
request.httpMethod = "POST"
let postString = "grant_type=password&username=ABCDEF&password=ABCDEF"
request.httpBody = postString.data(using: .utf8)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request)
{
data, response, error in
guard let data = data, error == nil else
{
// check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200
{
// check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
do
{
if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject]
{
g_token = (jsonObject["access_token"] as? String)!
print(g_token)
g_token_type = (jsonObject["token_type"] as? String)!
print("\n")
print(g_token_type)
funcResult = true ;
}
}
catch let error as NSError
{
print(error)
}
}
task.resume()
return funcResult
}
}
Here is my problem: When I click button, it gives me a token in output screen in Xcode (print) but getTokenWithPostMethod() method returns false. Why does it return false? During the debug process, it jumps from let task = to task.resume(). Thanks! (by the way I can't share correct link, username and password. I hope these 3 are not necessary to fix this problem)
You are making an API call. It takes time to return the value. Here return statement will not wait for response. you should use either closure or delegate. You can try the given code:
func getTokenWithPostMethod(handler: #escaping (_ funcResult: Bool) -> Void){
var request = URLRequest(url: URL(string: "https://apiABCDEFG.com/token")!)
request.httpMethod = "POST"
let postString = "grant_type=password&username=ABCDEF&password=ABCDEF"
request.httpBody = postString.data(using: .utf8)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request)
{
data, response, error in
var funcResult = false
if error == nil, let data = data {
do
{
if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject]
{
g_token = (jsonObject["access_token"] as? String)!
print(g_token)
g_token_type = (jsonObject["token_type"] as? String)!
print("\n")
print(g_token_type)
funcResult = true
}
}
catch let error as NSError
{
print(error)
}
}
// edited
DispatchQueue.main.async {
handler(funcResult)
}
}
task.resume()
}
This will return after the response comes. Replace the calling of that method with :
#IBAction func btnHitWebServiceClick(_ sender: Any) {
getTokenWithPostMethod { (flag) in
if flag {
lblResult.text = "yes, we get token: " + g_token
} else {
lblResult.text = "there is an error, please try again later"
}
}
}
For more details please visit
It is returning false because, you have set var funcResult = false in starting, so before URLSession request to server and return some data in response only, your function returns the funcResult value.
you can add below code inside URLSession task body, immediately after try catch, instead of adding it inside btnHitWebServiceClick :
if (getTokenWithPostMethod() == true)
{
lblResult.text = "yes, we get token: " + g_token
}
else
{
lblResult.text = "there is an error, please try again later"
}

XCTest performance testing of POST API

I am implementing Unit Test for my iOS swift project. I want to implement performance test for the POST API which I had in my project, but I don't know how to implement that POST API. I have tested GET APIs and that give me desired results.
Here's the code what I am trying to implement
func testPerfromancePOSTAPI() {
let session = URLSession.shared
var request = URLRequest(url: MY_URL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: MY_SERVICE_PARA, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
self.measure {
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print("response JSON = \(json)")
}
} catch let error {
XCTFail("Expectation Failed with error: %#", file: error as! StaticString);
}
})
task.resume()
}
}
When I run this test it passes successfully but doesn't print the response JSON and neither gives an error and shows that "Time 0.0000 sec (161% STDEV)", while running the same API in postman it takes few sec.
Please check and help me out this.
Try changing ur code as follows
func testPerfromancePOSTAPI() {
let session = URLSession.shared
var request = URLRequest(url: MY_URL)
let expectations = expectation(description: "POST")
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: MY_SERVICE_PARA, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
self.measure {
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print("response JSON = \(json)") expectations.fulfill()
}
} catch let error {
XCTFail("Expectation Failed with error: %#", file: error as! StaticString);
}
})
task.resume()
self.waitForExpectations(timeout: 10) { (error) in
if let error = error {
XCTFail("Error: \(error.localizedDescription)")
}
}
}
}
Change the timeout value to a higher one, if u still not getting any responses.
Defining expectation inside the measure block will works to measure performance.
func testPostAPIFetchParseTime() {
let session = URLSession.shared
var request = URLRequest(url: MY_URL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: MY_SERVICE_PARA, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
self.measure {
let expectations = self.expectation(description: "POST API performance check")
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print("response JSON = \(json)")
expectations.fulfill()
}
} catch let error {
XCTFail("Expectation Failed with error: %#", file: error as! StaticString);
}
})
task.resume()
self.waitForExpectations(timeout: 10.0) { (error) in
if let error = error {
XCTFail("Error: \(error.localizedDescription)")
}
}
}
}

Send Nested JSON With POST Request iOS Swift 3

I want to send JSON to Server with POST request but i did not understand how i do this. I select friends from table view and show these friends in my Collection view. And the selected peoples shows in collection views and their email are sent in JSON to Create group. Here is my code written in Swift.
#IBAction func createGroupButton(_ sender: Any) {
let groupName = groupNameTextField.text
let adminEmail = UserDefaults.standard.value(forKey: "userEmail")
if groupName == "" {
alertMessage(msg: "Enter Group name")
}
else if base64String == nil {
alertMessage(msg: "Select Group Image")
}
else if emailArray.isEmpty {
alertMessage(msg: "Select atleast one person")
}
else {
if isNetAvailable {
var emailData: String?
print("email data \(emailArray)")
for i in emailArray {
emailData = "\"email\":\"\(i)\""
}
let postData = "\"name\":\"\(groupName!)\",\"adminemail\":\"\(adminEmail!)\",\"image\":\"\(base64String!)\",\"emailArray\":\"\(emailData!)\""
let postDat = "jsondata={\(postData)}"
print("Post Data \(postDat)")
let urlString = create_group
let url = URL(string: urlString)
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = postDat.data(using: String.Encoding.utf8)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
print("Something wrong with creating Group")
}
if data == nil {
print("Nil Data")
}
if response == nil {
print("Nil Response")
}
if response != nil {
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("Response String is \(responseString)")
}
}
task.resume()
}
else {
alertMessage(msg: "Internet Not Available")
}
}
}
Here is my API
<?php
if($_SERVER["REQUEST_METHOD"] !="POST"){ exit; }
require_once 'dbcon.php';
if (!empty($_POST['jsondata']))
{
$configjson = $_POST['jsondata'];
$config = json_decode($configjson, true);
$groupname = $config['name'];
$adminemail = $config['adminemail'];
$image = $config['image'];
$queryemailcheck = "SELECT * FROM groups_name WHERE admin = '$adminemail' AND groupname = '$groupname'";
$selectquery = mysqli_query($connect, $queryemailcheck);
$totalemails= mysqli_num_rows($selectquery);
if($totalemails>0)
{
echo "Already exist";
}
else {
$queryinsert= "INSERT INTO groups_name(admin , groupname , pic ) VALUES('$adminemail' ,'$groupname' , '$image')";
if(mysqli_query($connect, $queryinsert)){
echo "Successfully Saved";
}else{
echo "Error: " ;
}
$members = $config['emailArray'];
foreach($members as $row ){
$email = $row['email'];
$queryinsert2= "INSERT INTO group_members(groupname , member , status ) VALUES('$groupname' ,'$email' , '0')";
if(mysqli_query($connect, $queryinsert2)){
echo "Successfully Saved";
}else{
echo "Error: " ;
}
}
}
}
else echo "post data is empty";
?>
You can use Alamofire library for handling your webservices. like
Alamofire.request(logoutUrl, method: .post, parameters: dict, encoding: JSONEncoding.default, headers:["Authorization":"Bearer \(accessToken)", "Accept":"application/json", "Content-Type":"application/json; charset=UTF-8"]).responseJSON { (response) in
let json:JSON = JSON(response.result.value)
let status = json["status"].stringValue
let statusCode = response.response?.statusCode
Create network handler class where you can hit webservices from all of your app.
func makeHttpPostRequest(uri:String, postBody:Dictionary<String, Any> ,Completion:#escaping (_ response: AnyObject, _ success: Bool) -> Void) {
let networkCheck = self.getNetworkStatus()
if networkCheck == false {
Completion("NO internet connection." as AnyObject,false)
return
}//end network check block
var urlRequest = self.makeHttpRequestWithUrl(url: uri)
urlRequest.httpMethod = "POST"
urlRequest.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
//check and set authorization header
if (UserDefaults.standard.object(forKey: AppConstant.KAppAuthenticationToken) != nil) {
let authToken = UserDefaults.standard.object(forKey: AppConstant.KAppAuthenticationToken) as! String
urlRequest.setValue("Token token="+authToken, forHTTPHeaderField: "Authorization")
}
//let postData = [self.addDefultParameters(detailDict: postBody)]
let jsonData = try? JSONSerialization.data(withJSONObject: postBody)
urlRequest.httpBody = jsonData
//create connection
self.httpConnectionWithRequest(request: urlRequest, Completion: Completion)
}
func makeHttpRequestWithUrl(url: String) -> URLRequest {
let urlString = AppConstant.baseUrl+url
let networkUrlRequest = URLRequest.init(url: URL.init(string: urlString)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 50)
return networkUrlRequest
}
func httpConnectionWithRequest(request: URLRequest, Completion:#escaping (_ response: AnyObject, _ success: Bool) -> Void) {
let session = URLSession.shared
// make the request
let task = session.dataTask(with: request) {
(data, response, error) in
// check for any errors
guard error == nil else {
print("error is: " + String.init(format: "%#", error?.localizedDescription as! CVarArg))
Completion(error!.localizedDescription as String as AnyObject, false)
return
}
// make sure we got data
guard let responseData = data else {
print("Error: did not receive data")
Completion("didn't get response data" as String as AnyObject, false)
return
}
let responseString = String.init(data: responseData, encoding: .utf8)
// parse the result as JSON, since that's what the API provides
if let resp = response as? HTTPURLResponse{
if (UserDefaults.standard.object(forKey: AppConstant.KAppAuthenticationToken) != nil) {
if resp.statusCode == 401{
//auth token expired
self.makeRequestWithNewToken(request: request, Completion: Completion)
}
}
//check if response is Array or dictionary
var jsonArray:[Any]?
var jsonDict:[String:Any]?
// response is in array
do{
jsonArray = try JSONSerialization.jsonObject(with: responseData, options: [])as? [Any]
}catch{
print("response doesn't contain array")
}
//response is in dictionary
do{
jsonDict = try JSONSerialization.jsonObject(with: responseData, options: [])as? [String:Any]
}catch{
print("response doesn't contain dict")
}
//=====
// if resp.statusCode == 200{
if jsonArray != nil{
Completion(jsonArray! as AnyObject, true)
return
}
if jsonDict != nil{
Completion(jsonDict! as AnyObject, true)
return
}
Completion("didn't get response data" as String as AnyObject, false)
return
}
}
task.resume()
}
And through the completion handler you will get the fetched data.

Resources