0

I'm building a very basic reddit client for iPhone, just to practice developing for iOS. I've gotten it to parse the JSON of my selected subreddit, however I'm unable to take the titles from the parsed JSON and display them in my UITableView. The problem I'm having at the moment is that I can't get my "postList" array to populate with the JSON data before the UITableView is loaded. So when the table views cells are being populated, there's nothing in the postList array's elements for them to be populated with. Any idea how to fix this?

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var tableView: UITableView!

let URL = "https://www.reddit.com/r/swift/.json"

var postList : [PostList] = Array(repeating: PostList(), count: 26)
//var postList : [PostList] = []
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    tableView.dataSource = self
    tableView.delegate = self
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.

}
//Setting up tableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 5
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: "aroundMeCell", for: indexPath)

    getPosts(url: URL, row: indexPath.row, cell: cell)
    let title = postList[indexPath.row].title
    cell.textLabel?.text = title
    return cell
}


//Receiving posts using Alamofire
func getPosts(url: String, row: Int, cell: UITableViewCell) {
    Alamofire.request(url, method: .get)
        .responseJSON { response in
            if response.result.isSuccess {
                let postJSON : JSON = JSON(response.result.value!)
                //print(postJSON)
                self.createPostListArray(json: postJSON, row: row, cell: cell)

            } else {
                print("Error: \(String(describing: response.result.error)) aaaaaa")
            }
    }
}

func createPostListArray(json: JSON, row: Int, cell: UITableViewCell) {

    let titlePath : [JSONSubscriptType] = ["data", "children", row, "data", "title"]
    let postPath : [JSONSubscriptType] = ["data", "children", row, "data", "selftext"]

    //Making sure I can unwrap both
    if(json[titlePath].string != nil && json[postPath].string != nil){
        let inTitle = json[titlePath].string!
        let inPost = json[postPath].string!
        postList[row].title = inTitle
        postList[row].post = inPost
    }
    else{
        print("error")
    }
}
4
  • I see many problems, from cellForRowAt you call Alamofire.request, passing the cell through the chain of calls, and then the cell (that can be dequeued, and so on...) arrive at its terminal place in "createPostListArray" and is not being used. For me, this code smells bad.
    – mugx
    Commented Dec 12, 2017 at 23:01
  • 2
    Probably unrelated to the issue but never create arrays with the Array(repeating:count: syntax. Declare the array empty var postList = [PostList]() and append or insert the items. And do not populate the data source array in cellForRowAt, do it in viewDidLoad.
    – vadian
    Commented Dec 12, 2017 at 23:02
  • Have you tried browsing other questions here at StackOverflow? Searching for your question title returns a lot of questions with seemingly similar issues :o)
    – agrm
    Commented Dec 12, 2017 at 23:06
  • Is this a code or some bad dish. Really it smells bad. You are doing almofire request in cellforrowatindexpath. Commented Dec 13, 2017 at 1:09

2 Answers 2

1

There are multiple issues with your code.

1- var postList : [PostList] = Array(repeating: PostList(), count: 26). You can create empty array var postList = [PostList]() and append of delete element on response.

2- Calling an api on cellForRowAt is not at all a good idea. Reason : whenever this method gets called you call an api. Think about a scenario that you are scrolling your tableview for every dequeue you will call this api.

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var tableView: UITableView!

let URL = "https://www.reddit.com/r/swift/.json"

var postList = [PostList]()
override func viewDidLoad() {
    super.viewDidLoad()
    getPosts(url: URL)
    tableView.dataSource = self
    tableView.delegate = self
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.

}
//Setting up tableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return postList.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: "aroundMeCell", for: indexPath)
    let title = postList[indexPath.row].title
    cell.textLabel?.text = title
    return cell
}


//Receiving posts using Alamofire
func getPosts(url: String) {
    Alamofire.request(url, method: .get)
    .responseJSON { [weak self] response in
        if response.result.isSuccess {
                    let postJSON : JSON = JSON(response.result.value!)
                //print(postJSON)
                self?.createPostListArray(json: postJSON)
                self?.tableView.reloadData()

            } else {
                print("Error: \(String(describing: response.result.error)) aaaaaa")
            }
    }
}

func createPostListArray(json: JSON) {
     //parse your json here, or read about objectMapper a pod. This will help you in parsing and if you are using swift 4, read encode json.
}
1

First do the api call in viewDidLoad() . Declare array as

      var postList = [PostList]

Perform self.tableview.reloadData() after api call success block.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.