Search code examples
iosswiftswift3alamofire

Pull to refresh not working


I am building my app in Swift 3 with Alamofire. I have JSON data coming into a list view. Every time I pull to refresh the content, instead of refreshing the content, it just adds more items to the bottom of the list in list view, instead of refreshing the visible list. I don't know what I could be doing wrong, my code so far is:

import UIKit
import Alamofire
import SVProgressHUD

struct postinput {
    let mainImage : UIImage!
    let name : String!
    let author : String!
    let summary : String!
    let content : String!


}


class TableViewController: UITableViewController {

    //var activityIndicatorView: UIActivityIndicatorView!

    var postsinput = [postinput]()

    var refresh = UIRefreshControl()

    var mainURL = "https://www.example.com/api"

    typealias JSONstandard = [String : AnyObject]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        tableView.separatorStyle = UITableViewCellSeparatorStyle.none


        self.tableView.addSubview(refresh)

        //;refresh.attributedTitle = NSAttributedString(string: "Refreshing...", attributes:[NSForegroundColorAttributeName : UIColor.black])
        refresh.backgroundColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0)
        //refresh.tintColor = UIColor.white

        refresh.addTarget(self, action: #selector(self.refreshData), for: UIControlEvents.valueChanged)
        //refresh.addTarget(self, action: #selector(getter: TableViewController.refresh), for: UIControlEvents.valueChanged)
        refresh.attributedTitle = NSAttributedString(string: "Updated: \(NSDate())")


        //activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
        //tableView.backgroundView = activityIndicatorView

        callAlamo(url: mainURL)


    }

    func refreshData() {

        Alamofire.request("https://www.example.com/api").responseJSON(completionHandler: {
            response in
            self.parseData(JSONData: response.data!)
            self.tableView.separatorStyle = UITableViewCellSeparatorStyle.singleLine

            DispatchQueue.main.async {
                self.tableView.reloadData()
                self.refresh.endRefreshing()
            }


        })



    }



    func callAlamo(url : String){
        //activityIndicatorView.startAnimating()
        SVProgressHUD.show(withStatus: "Loading...")
        SVProgressHUD.setDefaultStyle(SVProgressHUDStyle.dark)
        SVProgressHUD.setDefaultAnimationType(SVProgressHUDAnimationType.native)
        SVProgressHUD.setDefaultMaskType(SVProgressHUDMaskType.black)
        Alamofire.request(url).responseJSON(completionHandler: {
            response in
            self.parseData(JSONData: response.data!)
            self.tableView.separatorStyle = UITableViewCellSeparatorStyle.singleLine
            //self.activityIndicatorView.stopAnimating()
            SVProgressHUD.dismiss()


        })


    }


    func parseData(JSONData : Data) {
        do {
            var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard
            // print(readableJSON)

            if let posts = readableJSON["posts"] as? [JSONstandard] {
                for post in posts {
                    let title = post["title"] as! String

                    let author = post["author"] as! String

                    guard let dic = post["summary"] as? [String: Any], let summary = dic["value"] as? String else {
                        return
                    }
                    let str = summary.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
                    print(str)

                    guard let dic1 = post["content"] as? [String: Any], let content = dic1["value"] as? String else {
                        return
                    }
                    let str1 = content.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
                    print(str1)





                    //print(author)

                    if let imageUrl = post["image"] as? String {
                        let mainImageURL = URL(string: imageUrl )
                        let mainImageData = NSData(contentsOf: mainImageURL!)
                        let mainImage = UIImage(data: mainImageData as! Data)

                        postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary, content: content))
                    }
                }
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }


        }


        catch {
            print(error)
        }


    }


    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return postsinput.count
    }

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

        // cell?.textLabel?.text = titles[indexPath.row]

        let mainImageView = cell?.viewWithTag(2) as! UIImageView

        mainImageView.image = postsinput[indexPath.row].mainImage

        mainImageView.layer.cornerRadius = 5.0
        mainImageView.clipsToBounds = true

        //(cell?.viewWithTag(2) as! UIImageView).image = postsinput[indexPath.row].mainImage

        let mainLabel = cell?.viewWithTag(1) as! UILabel

        mainLabel.text = postsinput[indexPath.row].name

        mainLabel.font = UIFont.boldSystemFont(ofSize: 18)

        mainLabel.sizeToFit()

        mainLabel.numberOfLines = 0;

        let autLabel = cell?.viewWithTag(3) as! UILabel

        autLabel.text = postsinput[indexPath.row].author

        autLabel.font = UIFont(name: "Helvetica", size:16)

        autLabel.textColor = UIColor(red: 0.8784, green: 0, blue: 0.1373, alpha: 1.0) /* #e00023 */

        let sumLabel = cell?.viewWithTag(4) as! UILabel

        sumLabel.text = (postsinput[indexPath.row].summary).replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)

        sumLabel.font = UIFont(name: "Helvetica", size:16)

        sumLabel.textColor = UIColor(red:0.27, green:0.27, blue:0.27, alpha:1.0)

        //let contentLabel = cell?.viewWithTag(0) as! UILabel

        //contentLabel.text = (postsinput[indexPath.row].content).replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)



        //(cell?.viewWithTag(3) as! UILabel).text = postsinput[indexPath.row].author

        return cell!
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        SVProgressHUD.show()
        let indexPath = self.tableView.indexPathForSelectedRow?.row

        let vc = segue.destination as! nextVC


        vc.articleImage = postsinput[indexPath!].mainImage
        vc.articleMainTitle = postsinput[indexPath!].name
        vc.articleContent = postsinput[indexPath!].content
        SVProgressHUD.dismiss()

        let backItem = UIBarButtonItem()
        backItem.title = "Back"
        navigationItem.backBarButtonItem = backItem // This will show in the next view controller being pushed



    }


    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            postsinput.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
        } else if editingStyle == .insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
        }
    }

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


}

Solution

  • Your task here in pull to refresh is to just refresh the data existing in your list and also add the new items if any. So what you have to do is instead of keep on adding the items to your list everytime you pull-to-refresh, you just provide a new list coming from server to your tableView. Which you have the array aleready postsinput so make sure to remove all the items before you add it. Below is your code where you can do the changes.

     func parseData(JSONData : Data) {
    
        postsinput.removeAll()
    
        do {
    
            ...
            ...
                   if let imageUrl = post["image"] as? String {
                        let mainImageURL = URL(string: imageUrl )
                        let mainImageData = NSData(contentsOf: mainImageURL!)
                        let mainImage = UIImage(data: mainImageData as! Data)
    
                        postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary, content: content))
                    }
                }
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
           ...
           ...
    }