-2

I'm implementing chat feature in my app where I want to show more chat message when user pulls to refresh something similar to what we have on iMessage. I've been exploring various options but couldn't find any simple solution to implement this.

I've already implemented pull to refresh feature. Can anyone write steps or code to implement this feature either in pull to refresh function or using any table view delegate methods?

P.S. I don't want to use cocoapods or any 3rd party code.

Here is my pull to refresh function

    // Pull to refresh
    @objc func refresh(_ refreshControl: UIRefreshControl) {
    fetchMessages(completed: {
        self.messagesTable.reloadData()
    })

    refreshControl.endRefreshing()
}
DaveMS
  • 157
  • 2
  • 13
  • 2
    Welcome to SO. Please share what you already tried and what didn't work. If you are looking for someone to write your code, you probably want to look somewhere else. – koen Oct 23 '18 at 17:30
  • Didn't try any as I've no clue what exactly I need to do. I couldn't find any logic. I'm not asking anyone to wrote code. I want logic. – DaveMS Oct 23 '18 at 17:33
  • 2
    @DaveMS - google search for `swift uitableview pull-to-refresh` pulls up lots and lots of tutorials, demos, discussions, etc. Probably a good place to start. – DonMag Oct 23 '18 at 17:38
  • I'm not sure what you are asking for. Are you trying to get an implementation of the fetchMessages method? If so that is a little difficult not knowing your data source or any implementation details. Is there a reason for not wanting to use any 3rd party libraries? There are many that have almost built in chat functionality that you could easily implement. – GBreen12 Oct 23 '18 at 17:41
  • Possible duplicate of [Loading data into UICollectionView bunch by bunch](https://stackoverflow.com/questions/52945515/loading-data-into-uicollectionview-bunch-by-bunch) – Ratul Sharker Oct 23 '18 at 18:43
  • It's not clear to me what you're asking. Are you asking for the implementation of `fetchMessages`? – David Berry Oct 23 '18 at 19:05

2 Answers2

0

Think this as a paginated list of items. Let you fetch and show 100 item at a time. While the user request for more you fetch more 100 item and render it to your chat details page.

Now in general form you maintain an offset and limit variable which are type of Int. If you are familiar with offset and limit of a paginated api you can ignore the next section.

Say you first fetch 0-100th message in that case your offset would be 0 and limit would be 100. After the fetch operation completes your offset variable would be updated to 100. So next time you fetch, you fetch from 101-200th message and update the offset value to 200. This way you go ahead.

So you have to maintain a offset and limit. limit variable denote the number of item to fetch at once.

So whenever you pull to refresh the tableview, you fetch the items depending on offset & limit and populate the data items, then update the tableview.

Primarily to update the tableview just reload the tableview after populating the data arrays. If you want to only load the new items in the tableview take look at appledoc

func insertRows(at indexPaths: [IndexPath], 
       with animation: UITableView.RowAnimation)

Happy coding.

Ratul Sharker
  • 7,484
  • 4
  • 35
  • 44
  • 1
    Tx. This is what I'm looking for except that the array is in reverse direction i.e. I want to load more data at the top of screen when you pull to refresh like you see in iMessages. So first I'll fetch latest messages (let's say latest 100 message) then on pull to refresh fetch 100 more older messages and so on. So in my case I'll be prepending the items to array and reloading table. My concern is when I reload the table after fetching data it will reload entire (new) table? – DaveMS Oct 23 '18 at 17:55
  • After fetching you meant to store the msg's object into an array which is used in tableview`s datasource, so reloading the tableview would load the new items also. – Ratul Sharker Oct 23 '18 at 17:58
  • If you want to store the message object in local database using code data that is completely different story. You will connect the tableview to coredata query so that whenever the query result updates your tableview get updated automatically. In that case just storing the messages object in the coredata will sync up the tableview automatically. – Ratul Sharker Oct 23 '18 at 17:59
  • Take a look at the answer to this question: https://stackoverflow.com/questions/31870206/how-to-insert-new-cell-into-uitableview-in-swift It shows how to update the table without reloading all the data. It's more efficient. – GBreen12 Oct 23 '18 at 18:01
  • Yes this is what i suggested in the second part. First just reload the tableview and check that all the data are rendering or not. You may face some UI glitches like tableview scrolling to top/bottom, for those glitches and optimization you will insert the newly fetched item into your tableview using `insertRows` – Ratul Sharker Oct 23 '18 at 18:03
  • I'm not using any local database. I use web service to fetch chunk of, let's say, 100 message in each call. Confusion here. Let's say user pulls to refresh after loading initial messages. In this case object array will hold 200 messages (10 from initial load and next 100 from first pull). When I call tableview.reload it will reload all 200 message, how do we show the latest 100 messages instead of showing entire 200 messages. Do we need to scroll up to show correct index or how? – DaveMS Oct 23 '18 at 18:04
  • Yes you need to scroll to the last fetched item's first position. Actually it's depend upon your requirement or your choice, after fetching which item you wanted to show the user. Obviously you have to scroll to the choice of your decision. – Ratul Sharker Oct 23 '18 at 18:06
  • To only show 100 latest messages, return 100 in the `numberOfRowsInSection` function. – koen Oct 23 '18 at 18:39
0

Actually it's not pull to refresh in iMessage. It called lazy load. Lazy load means when you have a lot of data and you paginate it. So in order to get chat like table view with history:

  • Slice your chat database into small parts like 10-20 message per slice.
  • Load last slice in the table view.
  • In TableView...WillDisplayCellForRow... detect when the first row of table view will going to be displayed.
  • Load another slice and insert at the top of the table view
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • Yes you are also in right direction as I've seen it in various other answers and tuts. What happens to pull to refresh if we implement WillDisplayCellForRow? Do we have to remove pull to refresh? – DaveMS Oct 23 '18 at 17:57
  • There is no need to **pull** and no need to **refresh** since new messages not came from top like instagram or etc. ;) – Mojtaba Hosseini Oct 23 '18 at 18:03
  • 1
    I'm trying this method as this is the best I could understand at this point and it seems to be the easiest. Regarding the pull to refresh, I'll keep it as I want to show loading icon when user pulls to refresh exactly like it is in iMessages. – DaveMS Oct 24 '18 at 16:48