Achintya Gupta Achintya Gupta - 1 year ago 50
iOS Question

Adding a row to the top of a tableView

i am trying to add a row in an tableView on the top

let indexPath : [NSIndexPath] = [NSIndexPath(forRow: 0, inSection: 0)]

parentTableView.insertRowsAtIndexPaths(indexPath, withRowAnimation: .Fade)
but it is adding it to the bottom of tableView

This is my code :-

import UIKit

class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource,transferDelegate , UIViewControllerTransitioningDelegate{

var xibName : String = "HomepageFeedCellHeader"

var lords : [String] = ["name1","name2","name3"]

var queens : [String] = ["--","q1","q2"]

var desc : [String] = ["alpha","beta","gamma"]

var menProfilePictures : [UIImage] = [UIImage(named: "DaarioNaharis")!,UIImage(named: "JaimeLannister")!,UIImage(named: "LordVarys")!]

@IBOutlet weak var postButton: UIButton!

@IBOutlet weak var parentTableView: UITableView!

@IBOutlet weak var pickImages: UIButton!

var a : ParentTableViewCell = ParentTableViewCell()

@IBOutlet weak var postTextView: UITextView!

override func viewDidLoad() {


parentTableView.delegate = self
parentTableView.dataSource = self


func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return desc.count

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cell = parentTableView.dequeueReusableCellWithIdentifier("ParentCell", forIndexPath: indexPath) as! ParentTableViewCell

cell.transferingDelegate = self

cell.feedPostUsername.text = lords[indexPath.row]
cell.feedPostUserDetails.text = queens[indexPath.row]
cell.feedPostDescription.text = desc[indexPath.row]
cell.feedUserProfilePictures.image = menProfilePictures[indexPath.row]
cell.selectionStyle = .None

return cell


func transfer(itemNo : Int) {

print("call recieved in viewController from item \(itemNo)")

let imagePopOverScene = self.navigationController?.storyboard?.instantiateViewControllerWithIdentifier("ImagePopOverViewControllerVC_ID") as? ImagePopOverViewController

print("itemNo in viewControlle \(itemNo)")
if itemNo < 3{

imagePopOverScene?.setImage = menProfilePictures[itemNo]


imagePopOverScene?.setImage = UIImage(named: "defaultProfilePic")


imagePopOverScene?.transitioningDelegate = self

self.navigationController?.pushViewController(imagePopOverScene!, animated: true)


@IBAction func postBtnAction(sender: UIButton) {

print("post btn action recieved")


func tableViewConfiguration(){


menProfilePictures.append(UIImage(named: "defaultProfilePic")!)

let indexPath : [NSIndexPath] = [NSIndexPath(forRow: 0, inSection: 0)]
parentTableView.insertRowsAtIndexPaths(indexPath, withRowAnimation: .Fade)

tableView(parentTableView, cellForRowAtIndexPath: indexPath[0])


parentTableView.scrollToRowAtIndexPath(indexPath[0], atScrollPosition: UITableViewScrollPosition.Top, animated: true)


@IBAction func pickImagesAction(sender: UIButton) {



Answer Source

First of all, never call reloadData after calling insertRowsAtIndexPaths because insertRowsAtIndexPaths rearranges the table view implicitly.

But just this circumstance obscures the actual issue.

You're appending the new item(s) to the data source array(s) – by the way, why don't you use a custom struct instead of the three (edit: there are even four!) arrays – so they are physically at the end.

insertRowsAtIndexPaths inserts the item correctly at index 0 but the subsequent reloading of the table view moves the item according to the data source array again to the end of the table.

Solution: insert the item(s) at index 0 of the data source array(s) rather than append them.


A suggestion to use a custom struct

  • Declare that outside your view controller

    struct Avatar {
      let lord : String
      let queen : String
      let desc : String
      let profileImage : UIImage?
      init(lord: String, queen: String, desc: String, imageName: String) {
        self.lord = lord
        self.queen = queen
        self.desc = desc
        self.profileImage = UIImage(named: imageName)
  • In ViewController declare one data source array

    var avatars = [Avatar]()
  • In viewDidLoad populate the data source array

    override func viewDidLoad() {
        parentTableView.delegate = self
        parentTableView.dataSource = self
        avatars = [Avatar(lord: "name1", queen: "--", desc: "alpha", imageName: "DaarioNaharis"),
                   Avatar(lord: "name2", queen: "q1", desc: "beta", imageName: "JaimeLannister"),
                   Avatar(lord: "name3", queen: "q2", desc: "gamma", imageName: "LordVarys")]
  • In numberOfRowsInSection return avatars.count

  • In cellForRowAtIndexPath assign the properties

    let avatar = avatars[indexPath.row]
    cell.feedPostUsername.text = avatar.lord
    cell.feedPostUserDetails.text = avatar.queen
    cell.feedPostDescription.text = avatar.desc
    cell.feedUserProfilePictures.image = avatar.profileImage
  • Replace tableViewConfiguration with

    func tableViewConfiguration(){
        let newAvatar = Avatar(lord: "Anonymous", queen: "--", desc: postTextView.text!, imageName: "defaultProfilePic"
        avatars.insert(newAvatar, atIndex: 0)
        let indexPath = NSIndexPath(forRow: 0, inSection: 0)
        parentTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        parentTableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)