0

I have a tableviewController with 3 cells one for getting image and text from the server and the second for getting only text and the third one for implementing pagination with activity indicator like below in this image the 3 cells image


and this is the response of pagination:

{
    "statusCode": 200,
    "message": "Success",
    "data": {
        "result": [
            {
                "id": 28,
                "profileId": 12,
                "creatorId": 8,
                "postText": "اهلا وسهلا",
                "commentsCount": 0,
                "interactionsCount": 0,
                "createdAt": "2021-03-06T15:45:24.756Z",
                "updatedAt": "2021-03-06T15:45:24.756Z",
                "profile": {
                    "id": 12,
                    "logo": "https://onebusinessqrcode.s3.us-east-2.amazonaws.com/b562b93c-e278-5027-b615-edd399878c1a.jpg",
                    "name": "abdallah eslah",
                    "category": "Ecommerce",
                    "subCategory": "ElectronicMarket"
                },
                "creator": {
                    "id": 8,
                    "name": "abdallah eslah",
                    "image": "https://onebusinessqrcode.s3.us-east-2.amazonaws.com/0d362ee3-78e3-584a-8c34-6a91afa9dbda.png",
                    "email": "abdallaheslah@yahoo.com",
                    "mobile": "201094339599"
                },
                "media": [
                    {
                        "id": 396,
                        "postId": 28,
                        "media": "https://onebusinessqrcode.s3.us-east-2.amazonaws.com/2ad0ce30-a387-5c73-846a-eb414108fb72.jpg",
                        "createdAt": "2021-03-06T15:45:25.438Z",
                        "updatedAt": "2021-03-06T15:45:25.438Z"
                    }
                ]
            },
            {
                "id": 5,
                "profileId": 12,
                "creatorId": 8,
                "postText": "My new product",
                "commentsCount": 2,
                "interactionsCount": 0,
                "createdAt": "2021-03-01T07:13:39.400Z",
                "updatedAt": "2021-03-01T07:17:15.905Z",
                "profile": {
                    "id": 12,
                    "logo": "https://onebusinessqrcode.s3.us-east-2.amazonaws.com/b562b93c-e278-5027-b615-edd399878c1a.jpg",
                    "name": "abdallah eslah",
                    "category": "Ecommerce",
                    "subCategory": "ElectronicMarket"
                },
                "creator": {
                    "id": 8,
                    "name": "abdallah eslah",
                    "image": "https://onebusinessqrcode.s3.us-east-2.amazonaws.com/0d362ee3-78e3-584a-8c34-6a91afa9dbda.png",
                    "email": "abdallaheslah@yahoo.com",
                    "mobile": "201094339599"
                },
                "media": [
                    {
                        "id": 395,
                        "postId": 5,
                        "media": "https://onebusinessqrcode.s3.us-east-2.amazonaws.com/74c28cd0-47be-5053-85ca-c887cc36c781.jpg",
                        "createdAt": "2021-03-01T07:13:40.377Z",
                        "updatedAt": "2021-03-01T07:13:40.377Z"
                    }
                ]
            }
        ],
        "thisPage": 1,
        "allPages": 1,
        "count": 2
    }
}

so I used them in request below to get data and implement pagination :


//Used Variables in the request 
 var posts = [Posts]()
 var pictures = [UIImage]()

//Pagination Vars
 var allPages = 1
 var thisPage = 1

override func viewDidLoad() {
  super.viewDidLoad()
self.refreshControl = UIRefreshControl()
    self.refreshControl?.addTarget(self, action: #selector(refreshData), for: .valueChanged)
    self.refreshData()
 }

// MARK: - List All Posts
    @objc func refreshData(){
        thisPage = 1
        loadPosts(page: 1, refresh: true)
        
    }



@objc func loadPosts(page: Int,refresh: Bool = false) {
        
        if refresh {
   
            refreshControl?.beginRefreshing()
        }
        let profileId = UserDefaults.standard.value(forKey: "id") as? Int ?? 0
        
        var urlBuilder?.queryItems = [
        URLQueryItem(name: "profileId", value:"\(profileId)"), URLQueryItem(name: "page", value:"\(page)")
    ]
        
        guard let url = urlBuilder?.url else { return }
        
        var request = URLRequest(url: url)
        
        let token = UserDefaults.standard.value(forKey: "token") as? String ?? ""
        
        request.httpMethod = "GET"
        
        request.setValue(token, forHTTPHeaderField: "x-auth-token")
        
        // send request
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            DispatchQueue.main.async {
                
                if refresh {
                    self.posts.removeAll()
                    self.refreshControl?.endRefreshing()
                }
                
                // error occured
                if error != nil {
                    Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
                    return
                }
                
                do {
                    // access data - safe mode
                    guard let data = data else {
                        Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
                        return
                    }
                    
                    // converting data to JSON
                    let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary
                    
                    guard let parsedJSON = json else {
                        print("Parsing Error")
                        return
                    }
                    
                    if let data = parsedJSON["data"] as? NSDictionary {
                        self.allPages = data["allPages"] as? Int ?? 1

                        let object = Posts()

                        object.allPages = self.allPages
                      
                        if let posts = data["result"] as? [NSDictionary] {
                            for item in posts {
                                
                                
                                if let interactionsCount = item["interactionsCount"] as? Int {
                                    
                                    object.interactionsCount = interactionsCount
                                    
                                    
                                }
                                
                                
                                if let commentCounts = item["commentsCount"] as? Int {
                                    object.commentCounts = commentCounts
                                    
                                }
                                if let postMedia = item["media"] as? [NSDictionary] {
                                    if postMedia.count > 0 {
                                        let icon_images = postMedia
                                        
                                        object.multiImageIcon = icon_images
                                        //                                                                                                                            self.multiImages_Icon.isHidden = false
                                        if let media = postMedia[0]["media"] as? String {
                                            object.image = media
                                        }
                                    }
                                    
                                }
                                
                                if let profile = item["profile"] as? NSDictionary {
                                    
                                    if profile.count > 0 {
                                        
                                        if let name = profile["name"] as? String {
                                            
                                            object.name = name
                                            
                                        }
                                        
                                        if let logo = profile["logo"] as? String {
                                            
                                            object.ava = logo
                                            
                                            
                                        }
                                    }
                                }
                                
                                object.text = item["postText"] as? String
                                object.name = item["name"] as? String
                                object.date = item["createdAt"] as? String
                                object.id = item["id"] as? Int
                                object.ava = item["logo"] as? String
                                object.commentCounts = item["commentsCount"] as? Int
                                object.interactionsCount = item["interactionsCount"] as? Int
                                object.allPages = item["allPages"] as? Int
                                
                                self.posts.append(object)
                                self.tableView.reloadData()
                                
                            }
                        }
                    }
                } catch {
                    Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
                    return
                }
            }
        }.resume()
    }

finally the custom data source:

// MARK: - Table view data source

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

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if thisPage < allPages && indexPath.row == posts.count - 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "loading")
        return cell!
        
    }else {
        
        let pictureUrl = posts[indexPath.row].image ?? ""
    
        if pictureUrl.isEmpty == true {
        
        //5)=> accessing the text cell from main.storyboard
         let cell = tableView.dequeueReusableCell(withIdentifier: "NoPicCell", for: indexPath) as! NoPicCell
        
        
        cell.fullNameLabel.text = posts[indexPath.row].name?.capitalized ??
            UserDefaults.standard.value(forKey: "name") as? String
        
        cell.fullNameLabel.textColor = .label
        
        let postText = posts[indexPath.row].text
        
        cell.postTextLabel.text = postText
        cell.postTextLabel.textColor = .label
        
        let dateString = posts[indexPath.row].date
        
        let formatterGet = DateFormatter()
        formatterGet.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        
        let date = formatterGet.date(from: dateString ?? "")
        
        let formatterShow = DateFormatter()
        formatterShow.dateFormat = "MMMM dd yyyy - HH:mm"
        
        cell.dateLabel.text = formatterShow.string(from: date ?? Date())
        
        let postStars = posts[indexPath.row].interactionsCount ?? 0
        
        cell.starCountTwo.text = "\(postStars )"
        cell.starCountTwo.textColor = .label
        
        let postComments = posts[indexPath.row].commentCounts ?? 0
        
        cell.commentCountOne.text = "\(postComments)"
        cell.commentCountOne.textColor = .label
        
        let avaPath = UserDefaults.standard.value(forKey: "logo") as? String
        
        let ava = posts[indexPath.row].ava
        
        Helper().downloadImage(from: (ava ?? avaPath)! , showIn: cell.avaImageViewNoPic, orShow: "user.png")
        
        // Rounded corners
        cell.avaImageViewNoPic.layer.cornerRadius = cell.avaImageViewNoPic.frame.width / 2
        cell.avaImageViewNoPic.clipsToBounds = true
        
        cell.commentsButton.tag = indexPath.row
        cell.starButtonTwo.tag = indexPath.row
        cell.optionButton.tag = indexPath.row
        
        pictures.append(UIImage())
        
        return cell

    } else {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "PicCell", for: indexPath) as! PicCell
        
        let postText = posts[indexPath.row].text
        cell.postTextLabel.text = postText
        cell.postTextLabel.textColor = .label
        
        cell.fullNameLabel.text = posts[indexPath.row].name?.capitalized ?? UserDefaults.standard.value(forKey: "name") as? String
        
        cell.fullNameLabel.textColor = .label
        
        let dateString = posts[indexPath.row].date
        
        let formatterGet = DateFormatter()
        formatterGet.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        
        let date = formatterGet.date(from: dateString!)
        
        let formatterShow = DateFormatter()
        formatterShow.dateFormat = "MMMM dd yyyy - HH:mm"
        
        cell.dateLabel.text = formatterShow.string(from: date!)
        
        let postStars = posts[indexPath.row].interactionsCount ?? 0
        
        cell.starCountPic.text = "\(postStars )"
        cell.starCountPic.textColor = .label
        
        let postComments = posts[indexPath.row].commentCounts ?? 0
        
        cell.commentCountOne.text = "\(postComments)"
        cell.commentCountOne.textColor = .label
        
        let ava = posts[indexPath.row].ava
        
        let avaPath = UserDefaults.standard.value(forKey: "logo") as? String
        
        Helper().downloadImage(from: (ava ?? avaPath)! , showIn: cell.avaImageViewPic, orShow: "user.png")
        
        // Rounded corners
        cell.avaImageViewPic.layer.cornerRadius = cell.avaImageViewPic.frame.width / 2
        cell.avaImageViewPic.clipsToBounds = true
        
        cell.commentsButton.tag = indexPath.row
        cell.starButtonTwo.tag = indexPath.row
        cell.optionButton.tag = indexPath.row

        let pictureString = posts[indexPath.row].image
        
        let pictureURL = URL(string: pictureString ?? "")
        
        
        cell.pictureImageView.kf.setImage(with: pictureURL)
        
        if timelinePosts.count != pictures.count {
            
        }else{
            print("Pic cashed")
            DispatchQueue.main.async {
                

            }
            
    }
        
        cell.commentsButton.tag = indexPath.row
        cell.starButtonTwo.tag = indexPath.row
        cell.optionButton.tag = indexPath.row
        
    return cell
        }
    }
}

the willDisplay method :


override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if thisPage < allPages && indexPath.row == posts.count - 1 {
            thisPage = thisPage + 1
        loadPosts(page: thisPage,refresh: false)
        }
    }

1 Answers1

0

Move reload line out of for loop

  self.posts.append(object) 
} 
self.tableView.reloadData()
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • solved by removing posts.removeAll() in if refresh { refreshControl?.beginRefreshing() }. and I edited the question now I need to remove repeated posts from the server I got the data twise – abdallah eslah Mar 07 '21 at 10:19