1

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

}

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

11 Comments

Thank you so much for the insight. I'm using the script TinderSwipeView and the currentIndex is one of the values I've struggled with. When I replace index with currentIndex I get an 'Index out of range'.
What does index do, what is it used for, where changed and why, for what? Same for currentIndex . This matters since you use it to access var reviewed: [String] with it, the username-array.
@techgirl I ask this since you simply say „the other index gave me out-of-range“ without explaining why you would use the other instead of the current variable. If they are just indexes, to be replaced one with the other, then they can be used for no task at all, since the values are unknown due to interchengable use. What I mean to say is I don‘t see their purpose from the shown code.
I removed index and currentIndex and tried it with just reviewed 2 = reviewed. When I print the results it shows as ["user1", "user2", "user3"] and doesn't insert anything into the db.
If I were mean I would say: Just set let MAX_BUFFER_SIZE = 3; to 100, or whatever, dunno how that changes things for you but it should fix your „3“-problem. But.. Anyway, inside func removeObjectAndAddNewValues(), which is executed on each swipe, the first card in currentlyLoadedCards gets removed and a new one added from allCardsArray, so currentlyLoadedCards should not go out of cards any time soon, as long as allCardsArray is „filled“, see the if-condition in func removeObjectAndAddNewValues(). The developer probably didn‘t want to hold 1000 views in memory but 3 are okay
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.