How to wait the function execution until json loaded in Swift? - arrays

I am getting json file from url, then, all json output will be added in a array. When I print the array, it says that array is empty, but actually array is not empty I know. If I use like: DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { }, then, I can print the array.
My code to get json and adding its values to the array:
var allTags:Array<String> = []
func getJSON(getUrl:URL){
let url:URL = getUrl
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) {
(data, response, error) in
let dataString = String(data: data, encoding: String.Encoding.utf8)!
do {
let data = Data(dataString.utf8)
let dictionaries = (try? JSONSerialization.jsonObject(with: data)) as? [[String:Any]] ?? []
for dict in dictionaries {
let tags = dict["Tags"] as? [String] ?? []
for tag in tags {
allTags.append(tag)
}
}
}
}task.resume()
}
getJSON(getUrl: self.jsonUrl())
print(self.allTags.count) //it prints 0, but there are some data I know
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
print(self.allTags.count) //it prints 168
}

Use a callback:
var allTags:Array<String> = []
func getJSON(getUrl:URL, callback: #escaping () -> Void) {
let url:URL = getUrl
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
let dataString = String(data: data, encoding: String.Encoding.utf8)!
do {
let data = Data(dataString.utf8)
let dictionaries = (try? JSONSerialization.jsonObject(with: data)) as? [[String:Any]] ?? []
for dict in dictionaries {
let tags = dict["Tags"] as? [String] ?? []
for tag in tags {
allTags.append(tag)
}
}
callback()
}
}
task.resume()
}
getJSON(getUrl: self.jsonUrl()) {
print(self.allTags.count) // Should work now
}

var allTags:Array<String> = []
func getJSON(getUrl:URL, completion: #escaping () -> ()) {
let url:URL = getUrl
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) {
(data, response, error) in
let dataString = String(data: data, encoding: String.Encoding.utf8)!
do {
let data = Data(dataString.utf8)
let dictionaries = (try? JSONSerialization.jsonObject(with: data)) as? [[String:Any]] ?? []
for dict in dictionaries {
let tags = dict["Tags"] as? [String] ?? []
for tag in tags {
allTags.append(tag)
}
}
completion()
}
}task.resume()
}
getJSON(getUrl: self.jsonUrl()) { [weak self] in
guard let strongSelf = self else { return }
print(strongSelf.allTags.count)
}

Related

how convert JSON response to Array in swift?

func llamadaApiDos(postData: (Data),empresa: String,boundary: String) -> [String] {
var request = URLRequest(url: URL(string: "https://www.something.com")!,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
var success = false
var serviceResponse = [""]
let semaphore = DispatchSemaphore(value: 0)
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if let error = error {
print("Error while trying to re-authenticate the user: \(error)")
} else if let response = response as? HTTPURLResponse,
300..<600 ~= response.statusCode {
print("Error while trying to re-authenticate the user, statusCode: \(response.statusCode)")
} else if let data = data {
let loginDataModel = try! JSONDecoder().decode(responseLogin.self,from: data)
serviceResponse = JSONDecoder.decode(loginDataModel)
success = true
}else{
success = true
}
semaphore.signal()
})
task.resume()
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
if success
{
return serviceResponse
}else
{
return ["Error"]
}
}
Cannot assign value of type '(T.Type, Data) throws -> T' to type '[String]'
I need to convert the JSON response into an array that can be validated in another function, but I don't know what type of data I should return, I'm sorry if it's not well understood, my English isn't very good either.
To convert the JSON response to an array in Swift, you can use the JSONSerialization class to convert the response data to a dictionary, then access the array stored in the dictionary using the key for the array.
Here's an example:
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let array = json["keyForArray"] as? [String] {
// Use the array here
}
In your code, you can use this approach to convert the JSON response to an array, then return the array from the llamadaApiDos function.
Here's how your function would look like with this change:
func llamadaApiDos(postData: (Data),empresa: String,boundary: String) -> [String] {
var request = URLRequest(url: URL(string: "https://www.something.com")!,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
var success = false
var serviceResponse = [""]
let semaphore = DispatchSemaphore(value: 0)
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if let error = error {
print("Error while trying to re-authenticate the user: \(error)")
} else if let response = response as? HTTPURLResponse,
300..<600 ~= response.statusCode {
print("Error while trying to re-authenticate the user, statusCode: \(response.statusCode)")
} else if let data = data {
// Convert the JSON response to an array
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let array = json["keyForArray"] as? [String] {
// Use the array here
serviceResponse = array
success = true
}
}else{
success = true
}
semaphore.signal()
})
task.resume()
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
if success
{
return serviceResponse
}else
{
return ["Error"]
}
}

Escaping closure captures mutating 'self' parameter while decode JSON Swift

I try to parse JSON with mvc pattern.I'm trying for the first time. But I'm getting "Escaping closure captures mutating 'self' parameter error " I mutated functions and put self where necessary.I can access and use required protocols in ViewController. Everything seems normal What's the problem here ?
import Foundation
protocol ItunesManagerDelegate {
func didUpdateSearchin(_ ItunesManager:ItunesManager, product: [ItunesModel])
func didFailWithError(error:Error)
}
struct ItunesManager {
let baseURL = "https://itunes.apple.com/search?term="
var delegate : ItunesManagerDelegate?
var itunesDataArray = [ItunesModel]()
mutating func getSearchResult(for terms:String){
let urlString = "\(baseURL)\(terms)"
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}
if let searchResult = self.parseJSON(data!){
self.delegate?.didUpdateSearchin(ItunesManager(), product: searchResult)
}
}
task.resume()
}
}
mutating func parseJSON(_ itunesData:Data) -> [ItunesModel]? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode([ItunesData].self, from: itunesData)
decodedData.forEach { (ItunesData) in
ItunesData.results.forEach { (SearchResults) in
let type = SearchResults.wrapperType
let name = SearchResults.collectionName
let url = SearchResults.artworkUrl100
let price = SearchResults.collectionPrice
let date = SearchResults.releaseDate
let itunesProductInfo = ItunesModel(collectionName: name, collectionPrice: price, artWorkUrl100: url, wrapperType: type, releaseDate: date)
itunesDataArray.append(itunesProductInfo)
}
}
return itunesDataArray
}catch{
delegate?.didFailWithError(error: error)
return nil
}
}
}

How to send JSON Array to POST request for Swift 3 iOS?

I am using the below post method to send JSON array, Please help to me solved below issue?
I need post json data like below ;
key = punchdata
{
"maids" : "649",
"misReason" : "test",
"uId" : "20",
"aDate" : "2020-04-24",
"punchArray" : [
{
"in_time" : "14:10:00",
"in_date" : "2020-04-24",
"out_date" : "2020-04-24",
"out_time" : "19:00:00"
}
]
}
Below I attached the postman request and response, please check ;
func sendJSONArrayToPost() {
let params2 = ["punchdata" : ["uId": "20",
"aDate":"2020-04-24",
"maids":"649",
"misReason":"test",
"punchArray": [
[
"in_date": "2020-05-07",
"in_time": "10:00:00",
"out_date": "2020-05-07",
"out_time": "13:00:00"
]]]] as [String : Any]
let url = "https://iiplccr.hrgird.com/owner/hrmessapi/applymissingPunch"
Alamofire.request(url, method: .post, parameters: params2, encoding:JSONEncoding.default, headers: nil)
.responseJSON { response in
debugPrint(response)
if let data = response.result.value{
if (data as? [String : AnyObject]) != nil{
if let dictionaryArray = data as? Dictionary<String, AnyObject?> {
if dictionaryArray.count > 0 {
var resCode = Int()
var resMessage = ""
if let success = dictionaryArray["success"] as? Int{
resCode = success
}
if let Msg = dictionaryArray["Msg"] as? String{
resMessage = Msg
}
}
}
}
}
}
}
Other Way :
let jsonDataDict: NSMutableDictionary = NSMutableDictionary()
let arrObj: NSMutableDictionary = NSMutableDictionary()
let jsonArrayDict: NSMutableArray = NSMutableArray()
jsonDataDict.setValue("\(mLoginUserId)", forKey: "uId")
jsonDataDict.setValue(dateArray[0], forKey: "aDate")
jsonDataDict.setValue(maidStr, forKey: "maids")
jsonDataDict.setValue(resason, forKey: "misReason")
for item in self.MissingPunchListArray {
arrObj.setValue(item.inDate, forKey: "in_date")
arrObj.setValue(item.inTime, forKey: "in_time")
arrObj.setValue(item.outDate, forKey: "out_date")
arrObj.setValue(item.outTime, forKey: "out_time")
jsonArrayDict.add(arrObj)
}
jsonDataDict.setValue(jsonArrayDict, forKey: "punchArray")
below is another function I am trying to do ;
let url = "https://iiplccr.hrgird.com/owner/hrmessapi/applymissingPunch"
var request = URLRequest(url: NSURL(string: url)! as URL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try! JSONSerialization.data(withJSONObject: ["punchdata": jsonDataDict])
Alamofire.request(request)
.responseJSON { response in
switch response.result {
case .failure(let error):
print("error: \(error)")
if let data = response.data, let responseString = String(data: data, encoding: .utf8) {
print("responseString: \(responseString)")
}
case .success(let responseObject):
print("responseObject: \(responseObject)")
}
}
I get below error:
[Data]: 37025 bytes
[Result]: FAILURE: responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(error: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
You can try this way
var JsonDic = [String:Any]()
JsonDic["maids"] = "649"
JsonDic["misReason"] = "test"
JsonDic["uId"] = "20"
JsonDic["aDate"] = "2020-04-24"
let arr = [[String: String]]()
var obj = [String: String]()
obj["in_time"] = "14:10:00"
obj["to_city_id"] = "2020-04-24"
obj["out_date"] = "2020-04-24"
obj["out_time"] = "19:00:00"
arr.append(obj)
JsonDic["punchArray"] = arr

Getting Data from JSON Swift

Can Anyone Help me with this
my data after parsing a JSON URL is
{
AREA = (
{
"area_name" = "Bhaktamadhu Nagar";
"city_id" = 4;
id = 31;
price = "100.00";
},
{
"area_name" = "Gandamunda";
"city_id" = 4;
id = 32;
price = "100.00";
}
);
}
and there is a lot more.
I want to fetch only area_name and price values in an array
my code is something like that
do {
let parsedData = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! NSDictionary
print(parsedData)}
I am getting my Upper format in the parsedData
What is the exact code for getting my area_name and price which should store in two separate arrays as aname[] and price[]
Please don't mark it as a duplicate already searched a lot before posting this.
Your JSON data is converted into [String: AnyObject].
AREA data is [[String: AnyObject]] so create a [String: AnyObject] array. and getting a one by one value from array.
How to fetch JSON data from a url using URLSession?
try this code. it's helpfull
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let jsonData = data {
do {
let parsedData = try JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves) as! [String: AnyObject]
if let area = parsedData["AREA"] as? [[String: AnyObject]] {
for a in area {
areaNameArr.append(a["area_name"])
priceArr.append(a["price"])
print(a)
}
}
}
catch let error {
debugPrint(error)
}
}
else {
debugPrint(error as Any)
}
}.resume()
Use the SwiftyJSON Lib.
It’s easy and fast.
I am using it and it’s very helpful in this way:
let session = URLSession(configuration: URLSessionConfiguration.ephemeral)
self.Task = session.dataTask(with: RequestLink as URLRequest , completionHandler: { (data,response,error) in
if error != nil {
print(error as Any)
}
let ReadJson4Rest = JSON(data: data!)
if let Rest_Details = ReadJson4Rest["Result"].array{
for Details in Rest_Details {
let Comment = Details.dictionaryValue["Comment"]!
let UserName = Details.dictionaryValue["User_ID"]!
if Comment != nil {
let FirstChar = UserName.description.characters.first
self.GetUserImage(UserName: UserName.string! ,AlphabetCat: (FirstChar?.description)!)
DispatchQueue.main.async {
self.CommentValue.append(Comment.string!)
self.UserNames.append(UserName.string!)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Load"), object: nil)
}
}
}
}
})
self.Task?.resume()
}

"print array in main thread swift3 Xcode 8"

I learn swift not long ago and i have some problem in this code print array:
class InitController: UIViewController {
public var initdata = [(id: String, name: String)]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("initdata", initdata)
init_auth()
}
func init_auth(){
let json: [String: Any] = ["token": UserDefaults.standard.value(forKey: "token"), "id":UserDefaults.standard.value(forKey: "id")]
//let jsonData = try? JSONSerialization.data(withJSONObject: json)
let jsonData = try? JSONSerialization.data(withJSONObject: json)
let url = "http://some_ip/api"
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.httpBody = jsonData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//print(jsonData)
let task = URLSession.shared.dataTask(with: request) { data, responce, error in guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responceJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responceJSON = responceJSON as? [String: Any]{
let s = responceJSON["specialities"] as? NSDictionary
let d = s?["items"] as! NSArray
for i in d {
let f = i as? NSDictionary
self.initdata.append((id: f?["id"] as! String, name: f?["name"] as! String))
}
}
}
print("list", self.initdata)
task.resume()
}
}
initdata is empty array, but I get some json file and append this array. I try print initdata, but this array is nil. I think maybe problem in thread, but I don't know how realize this.
Try this -
func init_auth(){
let json: [String: Any] = ["token": UserDefaults.standard.value(forKey: "token"), "id":UserDefaults.standard.value(forKey: "id")]
//let jsonData = try? JSONSerialization.data(withJSONObject: json)
let jsonData = try? JSONSerialization.data(withJSONObject: json)
let url = "http://some_ip/api"
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.httpBody = jsonData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//print(jsonData)
let task = URLSession.shared.dataTask(with: request) { data, responce, error in guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responceJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responceJSON = responceJSON as? [String: Any]{
let s = responceJSON["specialities"] as? NSDictionary
let d = s?["items"] as! NSArray
for i in d {
let f = i as? NSDictionary
self.initdata.append((id: f?["id"] as! String, name: f?["name"] as! String))
}
print("list", self.initdata)
}
}
task.resume()
}

Resources