TableView在未捕获的异常下崩溃' NSUnknownKeyException',此类不是密钥x的密钥值编码兼容的密钥x。'

时间:2017-09-13 23:54:49

标签: swift3 tableview

我似乎无法使用自定义单元格来运行此tableView。我收到运行时错误

  

因未捕获的异常终止应用' NSUnknownKeyException',   原因:' [setValue:forUndefinedKey:]:这个类不是键   符合编码标准的密钥causeCampaignDescription。'

奇怪的是,该属性不再被称为那样。这是单元格文件 MainViewControllerTableViewCell

//
//  MainViewControllerTableViewCell.swift
// 
//
//  Created by on 9/13/17.
//  Copyright © 201. All rights reserved.
//

import UIKit

class MainViewControllerTableViewCell: UITableViewCell {


    @IBOutlet weak var causeCampaignImageView: UIImageView!



    @IBOutlet weak var causeDescription: UILabel!


    @IBOutlet weak var daysToFinishLabel: UILabel!


    @IBOutlet weak var raisedOverTotalLabel: UILabel!


    @IBOutlet weak var percentageCompletedLabel: UILabel!

    @IBOutlet weak var goalProgresView: UIProgressView!


    //card used on
    @IBInspectable var cornerradius : CGFloat = 2

    @IBInspectable var shadowOffSetWidth : CGFloat = 0

    @IBInspectable var shadowOffSetHeight : CGFloat = 5

    @IBInspectable var shadowColor : UIColor = UIColor.black

    @IBInspectable var shadowOpacity : CGFloat = 0.5



    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
    }

    override func layoutSubviews() {
        layer.cornerRadius = cornerradius
        layer.shadowColor = shadowColor.cgColor
        layer.shadowOffset = CGSize(width: shadowOffSetWidth, height: shadowOffSetHeight)
        let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: cornerradius)
        layer.shadowPath = shadowPath.cgPath
        layer.shadowOpacity = Float(shadowOpacity)
    }


}

这是保存表视图的视图控制器 MainViewController

//
//  ViewController.swift
// 
//
//  Created by on 1/28/17.
//  Copyright © 2017. All rights reserved.
//

import UIKit
import Alamofire
import SwiftyJSON
import Firebase


class MainViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {

    var campaignRowsData  = [CauseCampaign]()

    var serverFetchCampaignsUrl = Config.Global._serverUrl



    @IBOutlet weak var campaignTableView: UITableView!


    //show navigation controller bar

    var facebookID = "", twitterID = "",firebaseID = ""


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        //hide bar from navigation controller

        setToolbar()

        campaignTableView.delegate=self

        campaignTableView.dataSource=self

        campaignTableView.separatorColor = UIColor(white: 0.95, alpha: 1)

        recoverUserDefaults()

        getCampaignList()



        //print(facebookID, twitterID, firebaseID)

    }


    func setToolbar(){
        //hide bar from navigation controller
        self.navigationController?.isNavigationBarHidden = false

        self.navigationItem.setHidesBackButton(true, animated: false)

        self.navigationController?.navigationBar.barTintColor = UIColor.purple



    }

    func getCampaignList(){

        Alamofire.request(serverFetchCampaignsUrl+"/campaigns/get/all/user/\(twitterID)/firebase/\(firebaseID)/cat/0", method: .get).validate().responseJSON { response in
            switch response.result {
            case .success(let data):


                let campaignCausesJSON = JSON(campaignCausesData: data)

                self.parseCampaignCausesListResponse(campaignCausesJSON)

                //alternative thread operation


                DispatchQueue.main.async {
                    self.campaignTableView.reloadData()

                }

            case .failure(let error):
                print(error)
            }
        }

    }

    func parseCampaignCausesListResponse(_ campaignCausesJSON:JSON){

        if let activeCampaignCount = campaignCausesJSON["active_campaigns_count"].string {
            //Now you got your value
            print("TOTAL_ACTIVE_CAMPAIGNS",activeCampaignCount)
            CampaignsGlobalDataManagerUtil.campaignTotalCount = Int(activeCampaignCount)!
        }

        if let contributorUserId = campaignCausesJSON["contributor_user_id"].string {
            //Now you got your value
            print("CONTRIBUTOR_USER_ID",contributorUserId)
            CurrentUserUtil.contributorUserId = contributorUserId
        }

        if let userTwitterFollowersQty = campaignCausesJSON["user_twitter_followers_qty"].int {
            //Now you got your value
            print("USER_TWITTER_FOLLOWERS_QTY",userTwitterFollowersQty)
            CurrentUserUtil.twitterFollowersCount = Int(userTwitterFollowersQty)
        }

        //Parsing campaigns object array

          campaignCausesJSON["camp_array"].arrayValue.map({

            let campaignCause:JSON = $0

             parseCampaign(campaignCause)
          })




    }
    //TODO:CHANGE TO DATATAPE OBJECT
    func parseCampaign(_ causeCampaign:JSON){

        let causeCampaignObject: CauseCampaign = CauseCampaign();

        causeCampaignObject.description = causeCampaign["cause_description"].stringValue


        causeCampaignObject.id = causeCampaign["campaign_id"].stringValue


        if let contributorsQty = causeCampaign["contributors_qty"].int{
            causeCampaignObject.contributorsQty = contributorsQty

        }

        causeCampaignObject.currencySymbol = causeCampaign["currency_symbol"].stringValue

        if let currentContributions = causeCampaign["current_contributions"].float{
            causeCampaignObject.currentContributions = currentContributions

        }

        if let goal = causeCampaign["goal"].float {
            causeCampaignObject.goal = goal
        }

        if let goalPercentageAchieved = causeCampaign["goal_percentage_achieved"].float{
            causeCampaignObject.goalPercentageAchieved = causeCampaign["goal_percentage_achieved"].float!
        }

        causeCampaignObject.hashtag = causeCampaign["hashtag"].stringValue

        causeCampaignObject.name = causeCampaign["name"].stringValue

        if let remainingAmmountToGoal = causeCampaign["remaining_ammount_to_goal"].float{
            causeCampaignObject.remainingAmmountToGoal = remainingAmmountToGoal
        }

        if let picUrl =  causeCampaign["pic_url"].stringValue as? String {
            causeCampaignObject.picUrl = picUrl
        }

        if let campaignStartingDate = causeCampaign["created_at"].string{
            causeCampaignObject.campaignStartingDate = campaignStartingDate
        }

        if let campaignEndingDate = causeCampaign["campaign_ending_date"].string{
            causeCampaignObject.campaignEndingDate = campaignEndingDate

        }


        var foundationsArray = [Foundation]()

        causeCampaign["foundations"].arrayValue.map({

            let id = $0["foundation_id"].stringValue
            let twitterUsername = $0["twitter_username"].stringValue
            let picPath = $0["pic_path"].stringValue
            let name = $0["name"].stringValue

            let foundation:Foundation = Foundation(id,twitterAccount: twitterUsername,picPath: picPath,name: name)

            foundationsArray.append(foundation)
        })


        causeCampaignObject.foundations = foundationsArray


        campaignRowsData.append(causeCampaignObject)

//        foundations = "<null>";

//innecesario
//        SACAR DE LA REQUEST INICIAL???
//        "went_inactive_date" = "<null>";
//        "tweet_id" = 900936910494810112;


    }




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

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

       let cell = campaignTableView.dequeueReusableCell(withIdentifier: "campaignCell", for: indexPath) as! MainViewControllerTableViewCell

    //setting card attributes
        print("ROW",campaignRowsData[indexPath.row].description)
        let campaignCause:CauseCampaign = campaignRowsData[indexPath.row]

        if let desc = campaignCause.description as? String{
                cell.causeDescription.text = desc
        } else {
            print("NULL")
        }

        return cell
    }


    func recoverUserDefaults(){
        if let fbID = UserDefaults.standard.object(forKey: Config.Global._facebookIdUserDefaults) as? String {
            facebookID = fbID
        }else{
            print("FACEBOOK ID IS NULL")
        }



        if let twtID = UserDefaults.standard.object(forKey: Config.Global._twitterIdUserDefaults) as? String{
            twitterID = twtID
        }else{
            print("TWITTER ID IS NULL")
        }


        if  let firID = UserDefaults.standard.object(forKey: Config.Global._firebaseIdUserDefaults) as? String{
            firebaseID = firID
        }else{
            print("TWITTER ID IS NULL")
        }

        return
    }



}
  1. 如果行reloadData被取消注释,应用会崩溃(我甚至不知道何时以及如果我应该使用此行)
  2. 如果我设置标签,您无法在屏幕上看到任何内容,我会看到空白卡片,但是,一旦我取消注释reloadData它就会崩溃
  3. 没有causeCampaignDescription,现在它被称为causeDescription所以我不知道为什么错误会一直提到该字段
  4. 数据desc是正常的,因为我打印它并且它有正确的内容所以它不是那个
  5. 可能是什么问题?

1 个答案:

答案 0 :(得分:1)

在项目中搜索causeCampaignDescription通常会显示包含过时密钥路径的有问题的xib和/或故事板。然而,根据我的经验,Xcode并不总是100%可靠地在xibs和故事板中查找内容,所以如果Xcode的搜索功能找不到它,终端中的这个命令将立即将其打开:

find /path/to/your/project/directory -name .git -prune -or -type f -exec grep causeCampaignDescription {} \; -print

在xib或storyboard中找到有问题的项目后,将其更改为正确的字符串,您应该解决问题。