“这个类不是关键值编码兼容的密钥”错误

时间:2017-07-11 11:02:04

标签: ios swift key-value-observing

我收到此错误消息:

  

由于未捕获的异常'NSUnknownKeyException'而终止应用程序,原因:'[<Faceit.ViewController 0x7f8f72501e40> setValue:forUndefinedKey:]:此类不是关键面视图的键值编码兼容。'

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var faceView: FaceView! {
        didSet{
            updateUI()
        }
    }

    var expression = FacialExpression(eyes: .closed, mouth: .frown) {
        didSet {
            updateUI()
        }
    }

    private func updateUI() {
        switch expression.eyes {
        case .open:
            faceView?.eyesOpen = true
        case .closed:
            faceView?.eyesOpen = false
        case .squinting:
            faceView?.eyesOpen = false
        }
        faceView?.mouthCurvature = mouthCurvatures[expression.mouth] ?? 0.0
    }

    private let mouthCurvatures = [FacialExpression.Mouth.grin:0.5,.frown: -1.0,.smile:1.0,.neutral:0.0,.smirk:-0.5]

}

import Foundation

struct FacialExpression
{
    enum Eyes: Int {
        case open
        case closed
        case squinting

    }

    enum Mouth: Int {
        case frown
        case smirk
        case neutral
        case grin
        case smile

        var sadder: Mouth {
            return Mouth(rawValue: rawValue - 1) ?? .frown
        }
        var happier: Mouth{
            return Mouth(rawValue: rawValue + 1) ?? .smile
        }
    }

    var sadder: FacialExpression {
        return FacialExpression(eyes: self.eyes, mouth: self.mouth.sadder)
    }

    var happier: FacialExpression {
        return FacialExpression(eyes: self.eyes, mouth: self.mouth.happier)
    }

    let eyes: Eyes
    let mouth: Mouth
}

import UIKit

@IBDesignable
class FaceView: UIView {
    @IBInspectable
    var scale: CGFloat = 0.9

    @IBInspectable
    var eyesOpen: Bool = true

    @IBInspectable
    var lineWidth: CGFloat = 5.0

    @IBInspectable
    var mouthCurvature: Double = -0.5

    @IBInspectable
    var color: UIColor = UIColor.blue

    private var skullRadius : CGFloat {
        return min(bounds.size.width,bounds.size.height) / 2 * scale
    }
    private var skullCenter: CGPoint{
        return CGPoint(x: bounds.midX, y: bounds.midY)
    }

    private enum Eye{
        case left
        case right
    }
    private func pathForEye(_ eye:Eye) ->UIBezierPath{

        func centerForEye(_ eye: Eye) ->CGPoint{
            let eyeOffset = skullRadius / Ratios.skullRadiusToEyeOffset
            var eyeCenter = skullCenter
            eyeCenter.y -= eyeOffset
            eyeCenter.x += ((eye == .left ) ? -1 : 1)*eyeOffset
            return eyeCenter
        }

        let eyeRadius = skullRadius / Ratios.skullRadiusToEyeRadius
        let eyeCenter = centerForEye(eye)

        let path : UIBezierPath
        if eyesOpen{
            path = UIBezierPath(arcCenter: eyeCenter, radius: eyeRadius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)

        } else {
            path = UIBezierPath()
            path.move(to: CGPoint(x: eyeCenter.x - eyeRadius, y: eyeCenter.y))
            path.addLine(to: CGPoint(x: eyeCenter.x + eyeRadius, y: eyeCenter.y))
        }

        path.lineWidth = lineWidth
        return path
    }

    private func pathForMouth() ->UIBezierPath{
        let mouthWidth = skullRadius / Ratios.skullRadiusToMouthWidth
        let mouthHeight = skullRadius / Ratios.skullRadiusToMouthHeight
        let mouthOffset = skullRadius / Ratios.skullRadiusToMouthOffset

        let mouthRect = CGRect(
            x: skullCenter.x - mouthWidth/2,
            y: skullCenter.y + mouthOffset,
            width : mouthWidth,
            height : mouthHeight
        )

        let smileOffset = CGFloat(max(-1,min(mouthCurvature,1)))*mouthRect.height
        let start = CGPoint(x: mouthRect.minX, y: mouthRect.midY)
        let end = CGPoint(x: mouthRect.maxX, y: mouthRect.midY)

        let cp1 = CGPoint(x: start.x + mouthRect.width / 3, y: start.y + smileOffset)
        let cp2 = CGPoint(x: end.x - mouthRect.width / 3, y: start.y + smileOffset)
        let path = UIBezierPath()
        path.move(to: start)
        path.addCurve(to: end, controlPoint1: cp1, controlPoint2: cp2)

        path.lineWidth = lineWidth
        return path
    }

    private func pathForSkull() ->UIBezierPath{
        let path = UIBezierPath(arcCenter: skullCenter, radius: skullRadius, startAngle: 0, endAngle:  2 * CGFloat.pi, clockwise: false)
        path.lineWidth = 5.0
        return path
    }

    override func draw(_ rect: CGRect) {
        color.set()
        pathForSkull().stroke()
        pathForEye(.left).stroke()
        pathForEye(.right).stroke()
        pathForMouth().stroke()
    }

    private struct Ratios{
        static let skullRadiusToEyeOffset: CGFloat = 3
        static let skullRadiusToEyeRadius: CGFloat = 10
        static let skullRadiusToMouthWidth: CGFloat = 1
        static let skullRadiusToMouthHeight: CGFloat = 3
        static let skullRadiusToMouthOffset: CGFloat = 3
    }

}

3 个答案:

答案 0 :(得分:2)

请参阅:Thread 1: signal SIGABRT Xcode 6.1

您必须进入Interface Builder并查找具有警告三角形的一个(或多个)插座(按照屏幕截图链接)。一旦删除了那些不良连接,你就可以(1)准备好了,因为你已经连接了新对象,或者(2)你需要建立新连接,这样你就可以正确加载所有元素并且没有警告三角形。

答案 1 :(得分:1)

@vadian告诉我如何解决这个问题。它工作,改为faceview,也重新连接Interface Builder。 (这很重要)!

答案 2 :(得分:0)

打开你的故事板&gt;选择ViewController哪个类显示错误&gt;只需删除所有插座&gt;并重新分配插座。 希望你的问题能得到解决。这不是一个大问题,错误的是你有一个插座的多个键或不同的名称键,特别是它的faceview。