0

So far I only had to deal with simple JSON arrays with only a single array. I have now combined 2 arrays together so I can get my user data and all the reviews for that user:

[
{
    "user_id": "16",
    "name": "Jonh",
    "lastName": "appleseed",
    "username": "[email protected]",
    "sex": "male",
    "image_url": "",
    "review": [
        {
            "reviewID": "4",
            "merchant_id": "17",
            "rating": "5",
            "user_id": "16",
            "comments": "Very good customer. Strongly suggested",
            "date": "0000-00-00",
            "reviewYear": "",
            "publish": "1"
        },
        {
            "reviewID": "8",
            "merchant_id": "16",
            "rating": "2",
            "user_id": "16",
            "comments": "Automatic review due to "NO SHOW" without informing the merchant",
            "date": "0000-00-00",
            "reviewYear": "",
            "publish": "1"
        }
    ]
}
]

before I added the reviews my model looked like this:

import Foundation

class Users {
    let userImage:String?
    let name:String?
    let sex:String?
    let image_url:String?

    init(dictionary:NSDictionary) {            
        userImage = dictionary["userImage"]    as? String
        name = dictionary["name"]    as? String
        sex = dictionary["sex"]    as? String
        image_url = dictionary["image_url"]    as? String
    }
}

func loadUser(completion:(([Users])-> Void), userId: String){
    let myUrl = NSURL(string: "http://www.myWebSite.com/api/v1.0/users.php")
    let request = NSMutableURLRequest(URL: myUrl!)
    request.HTTPMethod = "POST"
    let postString = "user_id=\(userId)"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
        { data, response, error in        
            if error != nil {        
                print("error\(error)")    
            } else {
                do {     
                    let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSArray
                    print(json)

                    var users = [Users]()    
                    for user in json{                            
                        let user = Users(dictionary: user as! NSDictionary)    
                        users.append(user)    
                        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
                            dispatch_async(dispatch_get_global_queue(priority, 0 )){
                            dispatch_async(dispatch_get_main_queue()){        
                                    completion(users)
                            }
                        }    
                    }        
                } catch{   
                }
            }
        }
    task.resume()
}

which I could then used in my viewController:

func loadModel() {
    let loadingNotification = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
    loadingNotification.mode = MBProgressHUDMode.Indeterminate
    loadingNotification.labelText = "updating your deals..."
    users = [Users]()
    let api = Api()
    api.loadUser(didLoadUsers , userId: "16")    
}

func didLoadUsers(users:[Users]){        
    self.users = users
    self.tableView.reloadData()
    MBProgressHUD.hideAllHUDsForView(self.view, animated: true)
}

Can I get the review field so I can present it in a table view controller?

1
  • You should be able to get the "review" object the same was you are getting the strings, except it will be an array of dictionaries (not a string). Loop through the "review" array and do whatever you want with the dictionary. Commented Jan 4, 2016 at 17:04

2 Answers 2

1

I added to your Users class an array of reviews that will be populated in your user init() method. I recommend you to take look at struct Review and make your user class a struct, and change your NSDictionary to swift Dictionary.

   struct Review {
    let reviewID:String?
    let merchant_id:String?
    let user_id:String?
    //to be continued with your own implementation...

    init(dictionary:[String:String]) {
        reviewID = dictionary["reviewID"]
        merchant_id = dictionary["merchant_id"]
        user_id = dictionary["user_id"]
        //to be continued with your own implementation...
    }
}
class Users {

    let userImage:String?
    let name:String?
    let sex:String?
    let image_url:String?
    var reviews:[Review]

    init(dictionary:[String:AnyObject]) {

        userImage = dictionary["userImage"]    as? String
        name = dictionary["name"]    as? String
        sex = dictionary["sex"]    as? String
        image_url = dictionary["image_url"]    as? String
        reviews = [Review]()
        if let userReviews = dictionary["review"] as? [[String:AnyObject]] {
            for review  in userReviews {

                if let unwrapedReview = review as? [String:String] {
                    let r = Review(dictionary: unwrapedReview)
                    reviews.append(r)
                }
            }
        }
    }
}

Also I recommend you in the future to use SwiftyJSON for parsing JSON and also Alamofire for networking requests.

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

4 Comments

how can I get the values into the` reviews` array then?
if I print(user.reviews) I get myApp.Review(reviewID: Optional("8"), merchant_id: Optional("16"), user_id: Optional("16"))] ()
for review in user.reviews { print(review) }
thanks but I had to change my loadUser method and I created the UserReview class. Now I can load the reviews and users in my tableViewController
0

Done. It was easier than what I thought. I just had to add a UserReview class and change the signature of loadUser function:

 func loadUser(completion:((user: [Users], review: [UserReview])-> Void), userId: String){

    let myUrl = NSURL(string: "http://www.myWebsite.com/api/v1.0/users.php")
    let request = NSMutableURLRequest(URL: myUrl!)
    request.HTTPMethod = "POST"
    let postString = "user_id=\(userId)"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
        { data, response, error in

            if error != nil {

                print("error\(error)")

            }else{

                do{
                    let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSArray

                    var users = [Users]()


                    for user in json{

                        let user = Users(dictionary: user as! NSDictionary as! [String : AnyObject])

                        users.append(user)

        //*********** now I can access the reviews from my son***************
                     let reviewArray = json[0]["review"] as! NSArray
                        var reviews = [UserReview]()


                        for review in reviewArray{

                            let review = UserReview(dictionary: review as! NSDictionary as! [String : AnyObject])

                            reviews.append(review)

                        }

                        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
                        dispatch_async(dispatch_get_global_queue(priority, 0 )){

                            dispatch_async(dispatch_get_main_queue()){

                                completion(user: users, review: reviews)
                            }
                        }

                    }

                } catch{

                }
            }
    }
    task.resume()
}

So I can use it in my tableViewController

     var users: [Users]?
     var reviews: [UserReview]?

    func loadModel() {
    let loadingNotification = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
    loadingNotification.mode = MBProgressHUDMode.Indeterminate
    loadingNotification.labelText = "updating..."
    users = [Users]()
    reviews = [UserReview]()
    let api = Api()
    api.loadUser(didLoadUsers , userId: "16")
}

func didLoadUsers(users:[Users], reviews:[UserReview] ){

        self.users = users
        self.reviews = reviews
        self.tableView.reloadData()
        MBProgressHUD.hideAllHUDsForView(self.view, animated: true)    

    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if section == 0 {

        return users!.count

    }
    if section == 1 {   

        return 1  

    }
    if section == 2 {

    return reviews!.count
    }
    return 0
}

So in my cellForRowAtIndexPath I can now load all the reviews

if indexPath.section == 2 {

        let review = reviews![indexPath.row]


        let reviewCell = tableView.dequeueReusableCellWithIdentifier("reviewCell", forIndexPath: indexPath) as! UserReviewsTableViewCell
        reviewCell.useReview(review)

        return reviewCell
    }

Comments

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.