user12008081
user12008081

Reputation:

getting the error of NSUnknownKeyException', reason: setValue:forUndefinedKey: this class is not key value coding-compliant for the key description

I am facing the issue of passing the data from HomeViewController to PostDetailViewController, I have checked the classes connected to the View Controllers are correct, class connected to the XIB file is PostTableViewCell,

and still getting this error of

'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key description

upon clicking the tablecell

HOMEVIEWCONTROLLER

class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var tableView:UITableView!

    var posts = [Post]()
    var db: Firestore!

    var postKey:String = ""
    private var documents: [DocumentSnapshot] = []
    //public var posts: [Post] = []
    private var listener : ListenerRegistration!




    override func viewDidLoad() {
        super.viewDidLoad()

        db = Firestore.firestore()

        self.navigationController?.navigationBar.isTranslucent = false
        tableView = UITableView(frame: view.bounds, style: .plain)

        let cellNib = UINib(nibName: "PostTableViewCell", bundle: nil)
        tableView.register(cellNib, forCellReuseIdentifier: "postCell")
        tableView.backgroundColor = UIColor(white: 0.90,alpha:1.0)
        view.addSubview(tableView)

        var layoutGuide:UILayoutGuide!

        if #available(iOS 11.0, *) {
            layoutGuide = view.safeAreaLayoutGuide
        } else {
            // Fallback on earlier versions
            layoutGuide = view.layoutMarginsGuide
        }

        tableView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
        tableView.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true

        tableView.delegate = self
        tableView.dataSource = self
        tableView.reloadData()
        retrieveAllPosts()
        //checkForUpdates()

    }


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


    @IBAction func handleLogout(_ sender:Any) {
        try! Auth.auth().signOut()
        self.dismiss(animated: false, completion: nil)
    }


    func retrieveAllPosts(){
        let postsRef = Firestore.firestore().collection("posts").limit(to: 50)

        postsRef.getDocuments { (snapshot, error) in

            if let error = error {

                print(error.localizedDescription)

            } else {

                if let snapshot = snapshot {

                    for document in snapshot.documents {


                        let data = document.data()
                       // self.postKey = document.documentID
                        let username = data["username"] as? String ?? ""
                        let postTitle = data["postTitle"] as? String ?? ""
                        let postcategory = data["postcategory"] as? String ?? ""
                        let postContent = data["postContent"] as? String ?? ""

                        let newSourse = Post( _documentId: document.documentID, _username: username, _postTitle: postTitle, _postcategory: postcategory, _postContent: postContent)
                        self.posts.append(newSourse)
                        print(self.postKey)
                    }
                    self.tableView.reloadData()
                }
            }
        }
    }

       /* postsRef.getDocuments() { (querySnapshot, err) in
            if let err = err {
                print("Error getting documents: \(err)")
            } else {
                for document in querySnapshot!.documents {
                    print("\(document.documentID) => \(document.data())")


                    self.posts = querySnapshot!.documents.flatMap({Post(dictionary: $0.data())})
                    DispatchQueue.main.async {
                        self.tableView.reloadData()

        }
}
            }
        }*/
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tableView.reloadData()
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
        cell.set(post: posts[indexPath.row])
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let post = self.posts[indexPath.row]
        //print("row selected: \(indexPath.row)")
        //Swift.print(post._documentId!)
       let postKey = post._documentId
        let postName = post._username
        print(postKey! + postName!)
        performSegue(withIdentifier: "toDetailView", sender: indexPath)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
       //segue.forward(posts, to: segue.destination)
        guard let details = segue.destination as? PostDetailViewController,
        let index = tableView.indexPathForSelectedRow?.row

       else {
        return
        }
        details.detailView = posts[index]



    }

}

POSTTABLEVIEWCELL

class PostTableViewCell: UITableViewCell {

    @IBOutlet weak var usernameLabel: UILabel!
   @IBOutlet weak var profileImageView: UIImageView!
    @IBOutlet weak var subtitleLabel: UILabel!
    @IBOutlet weak var postTextLabel: UILabel!



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

       // profileImageView.layer.cornerRadius = profileImageView.bounds.height / 2
       // profileImageView.clipsToBounds = true
    }

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

        // Configure the view for the selected state
    }

    func set(post:Post) {
        usernameLabel.text = post._username
        postTextLabel.text = post._postTitle
        subtitleLabel.text = post._postcategory
    }

}

POST DETAIL VIEW CONTROLLER
class PostDetailViewController: UIViewController {

    @IBOutlet var usernamelabel: UILabel!


    @IBOutlet var posttitlelabel: UILabel!

    @IBOutlet var postIdlabel: UILabel!

   // @IBOutlet var description: UILabel!
    @IBOutlet var postcategorylabel: UILabel!

    var detailView: Post?
    var postId:String = ""
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        postIdlabel?.text = detailView?._documentId
        posttitlelabel?.text = detailView?._postTitle

    }


    /*
    // MARK: - Navigation

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

}

Upvotes: 1

Views: 71

Answers (1)

Bhavin Kansagara
Bhavin Kansagara

Reputation: 2916

This situations usually happens when you have already set IBOutlet in your XIB file and you comment out it's connecting outlets in code.

Here in your case, In your PostDetailViewController

// @IBOutlet var description: UILabel!

You have commented the description Label, but IBOutlet is still connected in your XIB file.

So, Look for your XIB file and checkout for active IBOutlet Connections and remove it for description label, Clean, Build and Run.

Hope it helps.

Upvotes: 0

Related Questions