Swift TableView segue to new ViewController with wrong index path (倒数第二个选择)

Posted

技术标签:

【中文标题】Swift TableView segue to new ViewController with wrong index path (倒数第二个选择)【英文标题】:Swift TableView segue to new ViewController with wrong index path (penultimate selection) 【发布时间】:2020-06-09 16:13:27 【问题描述】:

我有一个奇怪的问题。 我有两个 TableView,一个用于显示项目,一个用于显示所有团队成员。对于这两个 TableView,我有相同的错误。

当用户单击项目/团队成员时,我想显示它的详细信息。

奇怪的是,当我第一次运行应用程序并选择一个项目/团队成员时,什么都没有发生。然后当我选择另一个时,它会显示前一个选择的详细信息。 我希望有人可以帮助我。

还有一件奇怪的事情是,条目“Sarra Fezzani”已从 Firebase 数据库中删除,应用程序是干净构建的,但它仍然显示了好几次...

由于这两个代码非常相似,我将只发布 ProjetTableViewController 的代码,而不发布其他文件。

//
//  TeamViewController.swift
//  ProLabArtv2
//

import UIKit

class TeamViewController: UIViewController 


// MARK: - Properties


    @IBOutlet weak var memberTableView: UITableView!
    @IBOutlet weak var addTeamMember: UIButton!

    var members = [TeamMember]()
    var textToBeSent: String = ""

    override func viewDidLoad() 
        super.viewDidLoad()

        setUpElements()

        UserService.members(for: User.current)  (members) in
              self.members = members
              self.memberTableView.reloadData()
          

    

// MARK: - Element Style
    func setUpElements() 
         // Mark: Style the elements
        Utilities.addShadowtoButton(addTeamMember)
    


    func configureTableView() 
        // remove separators for empty cells
        memberTableView.tableFooterView = UIView()
        // remove separators from cells
        memberTableView.separatorStyle = .none
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        if segue.identifier == "toMemberDetails" 
            let destVC = segue.destination as! TeamMemberDetailsViewController
            destVC.member = sender as? TeamMember
        
    



// MARK: - UITableViewDataSource

extension TeamViewController: UITableViewDataSource 

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) 

        let member = members[indexPath.row]

        let cell = memberTableView.cellForRow(at: indexPath)

        print(members)

        performSegue(withIdentifier: "toMemberDetails", sender: member)
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return members.count
    


//    func numberOfSections(in tableView: UITableView) -> Int 
//        return members.count
//    


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
       let member = members[indexPath.row]

            let cell = memberTableView.dequeueReusableCell(withIdentifier: "TeamMemberCell") as! TeamMemberCell
        cell.jobLabel.text = members[indexPath.row].memberJob
        cell.nameLabel.text = members[indexPath.row].memberName


            return cell
        
    


// MARK: - UITableViewDelegate

extension TeamViewController: UITableViewDelegate 

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
     return 80
    


import UIKit

class TeamMemberCell: UITableViewCell 


// MARK: - Properties

    @IBOutlet weak var nameLabel: UILabel!
   @IBOutlet weak var jobLabel: UILabel!



static let height: CGFloat = 78

   override func awakeFromNib() 
       super.awakeFromNib()
       // Initialization code
   

   override func setSelected(_ selected: Bool, animated: Bool) 
       super.setSelected(selected, animated: animated)

       // Configure the view for the selected state
   



import Foundation
import UIKit
import FirebaseDatabase.FIRDataSnapshot




class TeamMember 

//      Next let's add properties to store all the additional information we need. Add the following to your post class.
    var key: String?
        let memberName: String
        let memberJob: String
        let memberLanguage: String
        let memberPrice: String
        let memberSpecification: String




//    You'll get some compiler errors for not having any initializers or default values for certain properties. Let's go ahead and fix that:

    init(memberName: String, memberJob: String, memberLanguage: String, memberPrice: String, memberSpecification: String) 
        self.memberName = memberName
        self.memberJob = memberJob
        self.memberLanguage = memberLanguage
        self.memberPrice = memberPrice
        self.memberSpecification = memberSpecification


    

    var dictValue: [String : Any] 


        return ["memberName" : memberName,
                "memberJob" : memberJob,
                "memberLanguage" : memberLanguage,
                "memberPrice" : memberPrice,
                "memberSpecification" : memberSpecification]

    
    init?(snapshot: DataSnapshot) 
        guard let dict = snapshot.value as? [String : Any],
            let memberName = dict["memberName"] as? String,
            let memberJob = dict["memberJob"] as? String,
            let memberLanguage = dict["memberLanguage"] as? String,
            let memberPrice = dict["memberPrice"] as? String,
            let memberSpecification = dict["memberSpecification"] as? String






            else  return nil 

        self.key = snapshot.key
        self.memberName = memberName
        self.memberJob = memberJob
        self.memberLanguage = memberLanguage
        self.memberPrice = memberPrice
        self.memberSpecification = memberSpecification

    

import Foundation
import FirebaseAuth.FIRUser
import FirebaseDatabase
import FirebaseUI
import FirebaseAuth


struct UserService 


    static func members(for user: User, completion: @escaping ([TeamMember]) -> Void) 
        let ref = Database.database().reference().child("team").child(user.uid)

           ref.observeSingleEvent(of: .value, with:  (snapshot) in
               guard let snapshot = snapshot.children.allObjects as? [DataSnapshot] else 
                   return completion([])
               

               let members = snapshot.reversed().compactMap(TeamMember.init)
               completion(members)
           )
       



//
//  TeamMemberDetailsViewController.swift
//  ProLabArtv2
//
//  Created by Manu on 09.06.20.
//  Copyright © 2020 Manuel Knott. All rights reserved.
//

import UIKit
import FirebaseDatabase
import FirebaseAuth
import FirebaseStorage

class TeamMemberDetailsViewController: UIViewController 

// MARK: - Properties

    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var jobLabel: UILabel!
    @IBOutlet weak var specificationLabel: UILabel!
    @IBOutlet weak var languageLabel: UILabel!
    @IBOutlet weak var priceLabel: UILabel!
    @IBOutlet weak var scoreLabel: UILabel!
    @IBOutlet weak var newScoreButton: UIButton!
    @IBOutlet weak var projectsPartButton: UIButton!


    var member: TeamMember?

    override func viewDidLoad() 
        super.viewDidLoad()

         setUI()

    

    func setUI() 

        nameLabel.text = member?.memberName
        jobLabel.text = member?.memberJob
        specificationLabel.text = member?.memberSpecification
        languageLabel.text = member?.memberLanguage
        priceLabel.text = member?.memberPrice
//        scoreLabel.text = member?.
    



这就是 ProjectViewController 的情况,我在其中使用 switch 语句...

//  HomeViewController.swift
//  ProLabArtv2
//

//

import UIKit
import Kingfisher
import Foundation
import FirebaseStorage
import FirebaseDatabase

class HomeViewController: UIViewController  

    // MARK: - Properties

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var addProject: UIButton!


    var posts = [Post]()



    var textToBeSent: String = ""
    override func viewDidLoad() 
        super.viewDidLoad()

        UserService.posts(for: User.current)  (posts) in
            self.posts = posts
            self.tableView.reloadData()
        

        Utilities.addShadowtoButton(addProject)

    

    func configureTableView() 
        // remove separators for empty cells
        tableView.tableFooterView = UIView()
        // remove separators from cells
        tableView.separatorStyle = .none
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        if segue.identifier == "toDetails" 
            let destVC = segue.destination as! ShowProjectDetailsViewController
            destVC.post = sender as? Post
        
    



// MARK: - UITableViewDataSource

extension HomeViewController: UITableViewDataSource 

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) 
        let post = posts[indexPath.row]
        performSegue(withIdentifier: "toDetails", sender: post)
    

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
      return 2
  

    func numberOfSections(in tableView: UITableView) -> Int 
        return posts.count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let post = posts[indexPath.section]

        switch indexPath.row 
        case 0:

            let cell = tableView.dequeueReusableCell(withIdentifier: "PostImageCell") as! PostImageCell
            let imageURL = URL(string: post.imageURL)
            cell.postImageView.kf.setImage(with: imageURL)

            return cell

        case 1:

            let cell = tableView.dequeueReusableCell(withIdentifier: "PostSubCell") as! PostSubCell
            cell.projectName.text = post.projectTitle



            return cell





        default:
            fatalError("Error: unexpected indexPath.")
        
    



// MARK: - UITableViewDelegate

extension HomeViewController: UITableViewDelegate 

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        switch indexPath.row 
        case 0:

           let post = posts[indexPath.section]
           return post.imageHeight

        case 1:

       return PostSubCell.height

        default:
            fatalError()
        
    
    

希望有人可以帮助我:)

【问题讨论】:

【参考方案1】:

这是我们都曾在某些时候犯过的错误之一,通常是由于没有仔细阅读自动完成。

你的代码是

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath)

您使用的是didDeselectRowAt 而不是didSelectRowAt 方法。这意味着它会在该行失去焦点时运行它(即当您单击另一行时)。

你需要

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        ...

【讨论】:

【参考方案2】:

您使用了错误的委托方法。在选择而不是de选择一个单元格

上执行segue
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    let post = posts[indexPath.row]
    performSegue(withIdentifier: "toDetails", sender: post)

【讨论】:

谢谢大家!真的帮了我很多:)

以上是关于Swift TableView segue to new ViewController with wrong index path (倒数第二个选择)的主要内容,如果未能解决你的问题,请参考以下文章

TableView 单元格,滑动操作和不同的 segues Swift 4

Swift 3 TableView Segue 到多个其他 TableViews

没有情节提要的 TableView Cell 的 iOS Swift Segue

使用动态tableView的tableViewCell中的动态collectionViewCell执行Segue With Identifier,swift

TableView、数组和segue

uicollectionview segue to detail viewcontroller swift