Значение индекса iOS TableView при прокрутке

Я использую табличное представление в своем проекте Swift. Проблема со значением пути индекса ячейки табличного представления. Когда таблица загружается изначально, значения индекса в порядке. Но как только я прокручиваю свое табличное представление, пути индекса ячейки изменяются, и идентификаторы, которые я получаю из массива данных, неправильны. Погуглите результаты, что это из-за многоразовой клеточной вещи. Вот мой код контроллера вида:

//
//  ProjectsController.swift
//  PMUtilityTool
//
//  Created by Muhammad Ali on 9/23/16.
//  Copyright © 2016 Genetech Solutions. All rights reserved.
//

import UIKit

class ProjectsController: UIViewController {

    //MARK: Properties
    var ProjectsArray: Array<Project> = []

    @IBOutlet weak var ProjectsTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.navigationController?.navigationBarHidden = true

        // Remove indenting of cell
        if self.ProjectsTableView.respondsToSelector(Selector("setSeparatorInset:")) {
            self.ProjectsTableView.separatorInset = UIEdgeInsetsZero
        }
        if self.ProjectsTableView.respondsToSelector(Selector("setLayoutMargins:")) {
            self.ProjectsTableView.layoutMargins = UIEdgeInsetsZero
        }

        self.ProjectsTableView.layoutIfNeeded()

        // Get projects
        getProjects()
    }

    override func viewWillAppear(animated: Bool) {
        self.navigationController?.navigationBarHidden = true
    }

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

    /*
     // MARK: - Navigation

     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */

    // MARK: - TableView Datasource
    func numberOfSectionsInTableView(tableView: UITableView) -> Int
    {
        return 1
    }

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

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        // print("clicked")
    }

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

        print(indexPath.row)

        let cell = tableView.dequeueReusableCellWithIdentifier("ProjectViewCell", forIndexPath:indexPath) as! ProjectTableViewCell

        // Remove indenting of cell
        cell.separatorInset = UIEdgeInsetsZero
        cell.layoutMargins = UIEdgeInsetsZero

        // Set project name
        cell.ProjectName.text = "\((indexPath.row)+1). \(self.ProjectsArray[indexPath.row].ProjectName)"

        // Set action button
        cell.ActionButton.tag = indexPath.row
        cell.ActionButton.addTarget(self, action: #selector(ProjectsController.projectActions(_:)), forControlEvents: .TouchUpInside)

        return cell

    }

    func reloadTableViewAfterDelay()
    {
        ProjectsTableView.performSelector(#selector(UITableView.reloadData), withObject: nil, afterDelay: 0.1)
    }

    @IBAction func projectActions(sender: UIButton) {
        let index = sender.tag

        let optionMenu = UIAlertController(title: nil, message: self.ProjectsArray[index].ProjectName, preferredStyle: .ActionSheet)

        // Report Progress
        let reportProgressAction = UIAlertAction(title: "Report Progress", style: .Default, handler: {
            (alert: UIAlertAction!) -> Void in
            self.performSegueWithIdentifier("ShowReportProgress", sender: sender)
        })

        // Cancel
        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: {
            (alert: UIAlertAction!) -> Void in

        })

        optionMenu.addAction(reportProgressAction)
        optionMenu.addAction(cancelAction)

        self.presentViewController(optionMenu, animated: true, completion: nil)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if let button = sender where segue.identifier == "ShowReportProgress" {
            let upcoming: ReportProgressController = segue.destinationViewController as! ReportProgressController
            print(self.ProjectsArray[button.tag].ProjectId)
            upcoming.ProjectId = self.ProjectsArray[button.tag].ProjectId
            upcoming.ProjectName = self.ProjectsArray[button.tag].ProjectName
        }

    }

    // MARK: Get Projects Function
    func getProjects() -> Void
    {

        var params = Dictionary<String,AnyObject>()
        params =  ["user_id":CFunctions.getSession("id")]

        WebServiceController.getAllProjects(params){ (type, response, message) -> Void in

            if (type == ResponseType.kResponseTypeFail)
            {

                // Show Error
                let alert = UIAlertController(title: "Error(s)", message:"Unable to load projects.", preferredStyle: .Alert)
                alert.addAction(UIAlertAction(title: "OK", style: .Default) { _ in })
                self.presentViewController(alert, animated: true){}

            }
            else
            {
                //debugPrint(response)

                if(response.count>0)
                {
                    self.ProjectsArray = response
                }
                else
                {
                    // Show Error
                    let alert = UIAlertController(title: "Error(s)", message:"No projects found.", preferredStyle: .Alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .Default) { _ in })
                    self.presentViewController(alert, animated: true){}
                }

                self.reloadTableViewAfterDelay()

            }
        }
    }

}

Я хочу, чтобы значение индекса каждой ячейки оставалось неизменным при прокрутке вниз или вверх.

4 ответа

Решение

Например, на экране вашего iPhone вы можете видеть 5 ячеек одновременно.

  1. Таким образом, при первой загрузке tableView метод cellForRowAtindexPAth будет вызываться для первых 5 ячеек.

    "Как вы упомянули, при первой загрузке индексы tableView верны".

  2. Теперь при прокрутке вниз метод cellForRowAtIndexPath будет вызываться только для 6 и 7.

    "До этого времени все работало нормально, как вы упомянули. КАК вы можете видеть общий путь индекса как неповрежденный 1,2,3,4,5,6,7".

    * Темные клетки в настоящее время видны на вашем экране.

  3. Теперь, когда вы прокрутите вверх {2 ячейки}. Теперь вы можете видеть текущие видимые ячейки на вашем экране 1,2,3,4,5.

Здесь, метод cellForRowAtIndexPath будет вызываться ТОЛЬКО для ячеек с номерами 2,1.

Потому что ячейки 3,4,5 уже загружены / видны на вашем экране.

Таким образом, ваш журнал печати будет 1,2,3,4,5,6,7,2,1.

Вам нужно получить indexPath кнопки, используя иерархию tableViewCell.

 @IBAction func projectActions(sender: UIButton) {
  let button = sender as! UIButton
  let view = button.superview!
  let cell = view.superview as! UITableViewCell
  let indexPath = self.reloadTableViewAfterDelay.indexPathForCell(cell)
  let index = indexPath.row
}

 if let button = sender where segue.identifier == "ShowReportProgress" {
       let upcoming: ReportProgressController =  segue.destinationViewController as! ReportProgressController
       let view = button.superview!
       let cell = view.superview as! UITableViewCell
       let indexPath = self.reloadTableViewAfterDelay.indexPathForCell(cell)
       let index = indexPath.row
       print(self.ProjectsArray[index].ProjectId)
       upcoming.ProjectId = self.ProjectsArray[index].ProjectId
       upcoming.ProjectName = self.ProjectsArray[index].ProjectName
       }

Вы должны добавить UITableViewDelegate а также UITableViewDataSource в ваш класс. и установить его ProjectsTableView.delegate = self в viewDidLoad,

Необходимо получить indexPath кнопки, используя tableViewCell, чем использованный ниже код

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cellId: NSString = "Cell"
    let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellId as String)! as UITableViewCell

    let ActionButton : UIButton = cell.viewWithTag(10) as! UIButton

    ActionButton.addTarget(self, action: #selector(ViewController.projectActions(_:)), forControlEvents: UIControlEvents.TouchUpInside)

    return cell
}

@IBAction func projectActions(sender: UIButton) {
    let buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
    let indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)
    print(indexPath?.row)

}
Другие вопросы по тегам