Swift passing same array value to PHP/MySQL - arrays

I have an app where a user reviews an array of users. Example:
["user1","user2","user3","user4"]
When the user reviews the first user the app should present the second user for voting. Unfortunately when a user votes on the user2, user3, user4; the value for user1 is what's put in the database. I tested the PHP via postman and there's no issue there, so it has to be in the swift code. Here is my code:
func loadCards()->[String] {
let username = user!["username"] as! String
let url = URL(string: "http://localhost/shotsCenter.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let body = "username=\(username)"
request.httpBody = body.data(using: .utf8)
// launch session
URLSession.shared.dataTask(with: request) { data, response, error in
// getting main queue of proceeding inf to communicate back, in another way it will do it in background
// and user will no see changes :)
DispatchQueue.main.async(execute: {
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: AnyObject]
// clean up
self.valueArray.removeAll(keepingCapacity: false)
self.circleArray.removeAll(keepingCapacity: false)
// delcare new secure var to store json
guard let parseJSON = json else {
print("Error while parsing")
return
}
// declare new secure var to store $returnArray["users"]
guard let parseUSERS = parseJSON["users"] else {
print(parseJSON["message"])
return
}
self.valueArray = parseUSERS as! [AnyObject]
if self.valueArray.count > 0 {
let num_currentLoadedCardsArrayCap = (self.valueArray.count > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : self.valueArray.count
for (i, value) in self.valueArray.enumerated() {
let ava = self.valueArray[i]["ava"]
let id = self.valueArray[i]["id"]
let age = (NSString(format: "%#", self.valueArray[i]["age"] as! CVarArg))
let city = self.valueArray[i]["city"]
let state = self.valueArray[i]["state"]
self.age.append(age as AnyObject)
self.city.append(city as AnyObject)
self.state.append(state as AnyObject)
let url = NSURL(string: ava! as! String)!
let imageData = try? Data(contentsOf: url as URL)
let image = UIImage(data: imageData!)!
self.circleArray.append(image)
let reviewed = self.valueArray[i]["username"]
self.reviewed.append((reviewed as AnyObject) as! String)
print("reviewed user", reviewed! as Any)
let newCard = self.createDraggableViewWithData(at: i, value:value as! NSDictionary)
self.allCardsArray.append(newCard)
if i < num_currentLoadedCardsArrayCap {
self.currentLoadedCardsArray.append(newCard)
}
}
for (i,_) in self.currentLoadedCardsArray.enumerated() {
if i > 0 {
self.viewTinderBackGround.insertSubview(self.currentLoadedCardsArray[i], belowSubview: self.currentLoadedCardsArray[i - 1])
}
else {
self.viewTinderBackGround.addSubview(self.currentLoadedCardsArray[i])
}
self.currentIndex += 1
}
self.animateCardAfterSwiping()
self.perform(#selector(self.createDummyCard), with: nil, afterDelay: 1.0)
}
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = "\(error)"
})
return
}
} else {
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
})
return
}
})
} .resume()
return reviewed
}
func insertShot(_ rating: String, _ reviewed2: NSDictionary) {
let reviewer = user!["username"] as! String
let reviewed2 = reviewed[index]
let url = URL(string: "http://localhost/shotsCenter.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// param to be passed to php file
let param = [
"user" : reviewer,
"revieweduser" : reviewed2,
"rating" : rating
] as [String : Any]
// body
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
// ... body
request.httpBody = createBodyWithParams(param as? [String : String], boundary: boundary)
// launch session
URLSession.shared.dataTask(with: request) { data, response, error in
// get main queu to communicate back to user
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 var to store json inf
guard let parseJSON = json else {
print("Error while parsing")
return
}
// get message from $returnArray["message"]
let message = parseJSON["message"]
//print(message)
// if there is some message - post is made
if message != nil {
// reset UI
// self.msgTxt.text = ""
// switch to another scene
//self.tabBarController?.selectedIndex = 3
//_ = self.navigationController?.popViewController(animated: true)
}
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = "\(error)"
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return
}
} else {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return
}
})
}.resume()
}

No idea what currentIndex is for. Sth about the view hierarchy?
index is an interesting candidate. The only times it is used is in
let reviewed2 = reviewed[index]
and I see no modification to it. Since usernames are stored in there with
let reviewed = self.valueArray[i]["username"]
I think you are sending the same username for all four ratings, since reviewed2 is then made of the .httpBody. That's a guess from what I can see.
Tip: Codable
Codable may save you a lot of the ugliness of juggling around with AnyObject & co, since you'll have a [User] array instead of.. 4 separate arrays which you access with [index]. https://app.quicktype.io will get you started quickly by providing you with the parsing code for the given JSON.

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 retrieve array of images from array of url swift

I'm trying to retrieve images from array of url..
I have this function that do the same as I won't but it doesn't work so I tried to use URLSession but didn't know how exactly to make it >>
func downloadImages(imageUrls: [String], completion: #escaping (_ images: [UIImage?]) -> Void) {
var imageArray: [UIImage] = []
var downloadCounter = 0
for link in imageUrls {
let url = NSURL(string: link)
let downloadQueue = DispatchQueue(label: "imageDowmloadQueue")
downloadQueue.sync {
downloadCounter += 1
let data = NSData(contentsOf: url! as URL)
if data != nil {
//image data ready and need to be converted to UIImage
imageArray.append(UIImage(data: data! as Data)!)
if downloadCounter == imageArray.count {
DispatchQueue.main.async {
completion(imageArray)
}
}
} else {
print("couldnt download image")
completion(imageArray)
}
}
}
}
The function I work on :
public func imagesFromURL(urlString: [String],completion: #escaping (_ images: [UIImage?]) -> Void) {
var imageArray: [UIImage] = []
var downloadCounter = 0
let downloadQueue = DispatchQueue(label: "imageDowmloadQueue")
for link in urlString {
downloadQueue.sync {
downloadCounter += 1
let dataTask = URLSession.shared.dataTask(with: NSURL(string: link)! as URL, completionHandler: { (data, response, error ) in
if error != nil {
print(error ?? "No Error")
return
}
if data != nil {
imageArray.append(UIImage(data: data! as Data)!)
if downloadCounter == imageArray.count {
completion(imageArray)
}
} else {
print("couldnt download image")
completion(imageArray)
}
} dataTask.resume()
}
}
}
i want to call the function in the collection cell and get the display the first image only from each artwork array..
//download the first image only to display it:
if artwork.ImgLink != nil && artwork.ImgLink.count > 0 {
downloadImages(imageUrls: [artwork.ImgLink.first!]) { (images) in
self.artworkImage.image = images.first as? UIImage
}
}
If you intend to use only the first available UIImage from an array of urls, you do not design a function trying to download all of them. Instead, try to download from the first url, return the downloaded UIImage if it succeeds, or continue with the second url if it fails, repeat until you get an UIImage.
Creating a DispatchQueue in a local function looks dangerous to me. A more common practice is to maintain a queue somewhere else and pass it to the function as a parameter, or reuse one of the predefined global queues using DispatchQueue.global(qos:) if you don't have a specific reason.
Be careful with sync. sync blocks the calling thread until your block finishes in the queue. Generally you use async.
Use a Int counter to control when to finish multiple async tasks (when to call the completion block) works but can be improved by using DispatchGroup, which handles multiple async tasks in a simple and clear way.
Here's two functions. Both work. firstImage(inURLs:completion:) only return the first UIImage that it downloads successfully. images(forURLs:completion:) tries to download and return them all.
func firstImage(inURLs urls: [String], completion: #escaping (UIImage?) -> Void) {
DispatchQueue.global().async {
for urlString in urls {
if let url = URL(string: urlString) {
if let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
DispatchQueue.main.async {
completion(image)
}
return
}
}
}
DispatchQueue.main.async {
completion(nil)
}
}
}
// Use it.
firstImage(inURLs: artwork.ImgLink) { image in
self.artworkImage.image = image
}
func images(forURLs urls: [String], completion: #escaping ([UIImage?]) -> Void) {
let group = DispatchGroup()
var images: [UIImage?] = .init(repeating: nil, count: urls.count)
for (index, urlString) in urls.enumerated() {
group.enter()
DispatchQueue.global().async {
var image: UIImage?
if let url = URL(string: urlString) {
if let data = try? Data(contentsOf: url) {
image = UIImage(data: data)
}
}
images[index] = image
group.leave()
}
}
group.notify(queue: .main) {
completion(images)
}
}
// Use it.
images(forURLs: artwork.ImgLink) { images in
self.artworkImage.image = images.first(where: { $0 != nil }) ?? nil
}

Json data - white console - Xcode 9

I am trying a simple app in which I want to convert some values. It worked until I tried to convert the data in a dictionary, and when I hit run, it builds successfully, but the console does not print anything. Here is the code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://gnb.dev.airtouchmedia.com/rates.json")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil
{
print("ERROR")
}
else {
if let content = data {
do {
//Array
let myJson = try JSONSerialization.jsonObject(with:content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
//print(myJson)
if let rate = myJson["rate"] as? NSDictionary {
if let currency = rate["AUD"] {
print(currency)
}
}
}
catch {
}
}
}
}
task.resume()
}
because you are parsing JSON wrongly
try this
let myJson = try JSONSerialization.jsonObject(with:content, options: JSONSerialization.ReadingOptions.mutableContainers) as? [[String: AnyObject]] else { return }
for rate in myJson
guard let cur = user["from"] as? String,
let curRate = user["rate"] as? Double else { break }
if let cur = "AUD" {
print(curRate)
}
Update:
You are receiving Array of Objects in response,
so first you have to treat it as Array of object,
Then you have to loop through this objects and then inside that loop you have to extract the data you were looking for and play with it.

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()
}

Resources