我采用了一个github项目,他以编程方式添加了一个按钮,但是我在接口构建器中添加了它,但它不起作用

时间:2017-07-02 19:46:16

标签: ios swift xcode swift3 xcode8

  

有人可以帮我解决这个github项目如何在我的项目中用一些代码实现

这段代码是我使用IB构建器创建按钮的代码,并为按钮创建了一个插座,并将其类更改为自定义类并添加了切换功能和.TouchUpInside行 而且我收到错误

  

致命错误:在展开Optional值时意外发现nil   2017-07-03 00:51:21.630176 + 0530 ala [867:183071]致命错误:在解包可选值时意外发现nil   (LLDB)

当我点击按钮并处于默认状态时,它甚至不可见

import UIKit

class serchViewController: UIViewController {
@IBOutlet weak var menuView: UIView!
@IBOutlet weak var menuBtn: HamburgerButton!

override func viewDidLoad() {
    super.viewDidLoad()
    let screenSize: CGRect = UIScreen.main.bounds
    menuView.frame = CGRect (x: 0, y: 0, width: screenSize.width/4, height: screenSize.height)
    self.menuBtn.addTarget(self, action: #selector(serchViewController.toggle(_:)), for: .touchUpInside)

    // Do any additional setup after loading the view.
}

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

func toggle(_ sender: AnyObject!) {
    self.menuBtn.showsMenu = !self.menuBtn.showsMenu
}


}

这是原始代码     导入UIKit

class ViewController: UIViewController {
var button: HamburgerButton! = nil

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor(red: 38.0 / 255, green: 151.0 / 255, blue: 68.0 / 255, alpha: 1)

    self.button = HamburgerButton(frame: CGRect(x: 133, y: 133, width: 54, height: 54))
    self.button.addTarget(self, action: #selector(ViewController.toggle(_:)), for:.touchUpInside)

    self.view.addSubview(button)
}

override var preferredStatusBarStyle : UIStatusBarStyle  {
    return .lightContent
}

func toggle(_ sender: AnyObject!) {
    self.button.showsMenu = !self.button.showsMenu
}
}

错误文件代码在

之下
import CoreGraphics
import QuartzCore
import UIKit

class HamburgerButton : UIButton {
let shortStroke: CGPath = {
    let path = CGMutablePath()
    path.move(to: CGPoint(x: 2, y: 2))
    path.addLine(to: CGPoint(x: 28, y:2))

    return path
}()

let outline: CGPath = {
    let path = CGMutablePath()
    path.move(to: CGPoint(x: 10, y: 27))
    path.addCurve(to: CGPoint(x: 40, y: 27), control1: CGPoint(x: 12, y: 27), control2: CGPoint(x: 28.02, y: 27))
    path.addCurve(to: CGPoint(x: 27, y: 02), control1: CGPoint(x: 55.92, y: 27), control2: CGPoint(x: 50.47, y: 2))
    path.addCurve(to: CGPoint(x: 2, y: 27), control1: CGPoint(x: 13.16, y: 2), control2: CGPoint(x: 2, y: 13.16))
    path.addCurve(to: CGPoint(x: 27, y: 52), control1: CGPoint(x: 2, y: 40.84), control2: CGPoint(x: 13.16, y: 52))
    path.addCurve(to: CGPoint(x: 52, y: 27), control1: CGPoint(x: 40.84, y: 52), control2: CGPoint(x: 52, y: 40.84))
    path.addCurve(to: CGPoint(x: 27, y: 2), control1: CGPoint(x: 52, y: 13.16), control2: CGPoint(x: 42.39, y: 2))
    path.addCurve(to: CGPoint(x: 2, y: 27), control1: CGPoint(x: 13.16, y: 2), control2: CGPoint(x: 2, y: 13.16))

    return path
}()

let menuStrokeStart: CGFloat = 0.325
let menuStrokeEnd: CGFloat = 0.9

let hamburgerStrokeStart: CGFloat = 0.028
let hamburgerStrokeEnd: CGFloat = 0.111

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override init(frame: CGRect) {
    super.init(frame: frame)

    self.top.path = shortStroke
    self.middle.path = outline
    self.bottom.path = shortStroke

    for layer in [ self.top, self.middle, self.bottom ] {
        layer?.fillColor = nil
        layer?.strokeColor = UIColor.blue.cgColor
        layer?.lineWidth = 4
        layer?.miterLimit = 4
        layer?.lineCap = kCALineCapRound
        layer?.masksToBounds = true

        let strokingPath = CGPath(__byStroking: (layer?.path!)!, transform: nil, lineWidth: 4, lineCap: .round, lineJoin: .miter, miterLimit: 4)

        layer?.bounds = (strokingPath?.boundingBoxOfPath)!

        layer?.actions = [
            "strokeStart": NSNull(),
            "strokeEnd": NSNull(),
            "transform": NSNull()
        ]

        self.layer.addSublayer(layer!)
    }

    self.top.anchorPoint = CGPoint(x: 28.0 / 30.0, y: 0.5)
    self.top.position = CGPoint(x: 40, y: 18)

    self.middle.position = CGPoint(x: 27, y: 27)
    self.middle.strokeStart = hamburgerStrokeStart
    self.middle.strokeEnd = hamburgerStrokeEnd

    self.bottom.anchorPoint = CGPoint(x: 28.0 / 30.0, y: 0.5)
    self.bottom.position = CGPoint(x: 40, y: 36)
    }

    var showsMenu: Bool = false {
    didSet {
        let strokeStart = CABasicAnimation(keyPath: "strokeStart")
        let strokeEnd = CABasicAnimation(keyPath: "strokeEnd")

        if self.showsMenu {
            strokeStart.toValue = menuStrokeStart
            strokeStart.duration = 0.5
            strokeStart.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)

            strokeEnd.toValue = menuStrokeEnd
            strokeEnd.duration = 0.6
            strokeEnd.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)
        } else {
            strokeStart.toValue = hamburgerStrokeStart
            strokeStart.duration = 0.5
            strokeStart.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, 0, 0.5, 1.2)
            strokeStart.beginTime = CACurrentMediaTime() + 0.1
            strokeStart.fillMode = kCAFillModeBackwards

            strokeEnd.toValue = hamburgerStrokeEnd
            strokeEnd.duration = 0.6
            strokeEnd.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, 0.3, 0.5, 0.9)
        }

        self.middle.ocb_applyAnimation(strokeStart)
        self.middle.ocb_applyAnimation(strokeEnd)

        let topTransform = CABasicAnimation(keyPath: "transform")
        topTransform.timingFunction = CAMediaTimingFunction(controlPoints: 0.5, -0.8, 0.5, 1.85)
        topTransform.duration = 0.4
        topTransform.fillMode = kCAFillModeBackwards

        let bottomTransform = topTransform.copy() as! CABasicAnimation

        if self.showsMenu {
            let translation = CATransform3DMakeTranslation(-4, 0, 0)

            topTransform.toValue = NSValue(caTransform3D: CATransform3DRotate(translation, -0.7853975, 0, 0, 1))
            topTransform.beginTime = CACurrentMediaTime() + 0.25

            bottomTransform.toValue = NSValue(caTransform3D: CATransform3DRotate(translation, 0.7853975, 0, 0, 1))
            bottomTransform.beginTime = CACurrentMediaTime() + 0.25
        } else {
            topTransform.toValue = NSValue(caTransform3D: CATransform3DIdentity)
            topTransform.beginTime = CACurrentMediaTime() + 0.05

            bottomTransform.toValue = NSValue(caTransform3D: CATransform3DIdentity)
            bottomTransform.beginTime = CACurrentMediaTime() + 0.05
        }

        self.top.ocb_applyAnimation(topTransform)
        self.bottom.ocb_applyAnimation(bottomTransform)
       }
    }

    var top: CAShapeLayer! = CAShapeLayer()
    var bottom: CAShapeLayer! = CAShapeLayer()
    var middle: CAShapeLayer! = CAShapeLayer()
  }

  extension CALayer {
func ocb_applyAnimation(_ animation: CABasicAnimation) {
    let copy = animation.copy() as! CABasicAnimation

    if copy.fromValue == nil {
        copy.fromValue = self.presentation()!.value(forKeyPath: copy.keyPath!)
    }

    self.add(copy, forKey: copy.keyPath)
    self.setValue(copy.toValue, forKeyPath:copy.keyPath!)
}
}

Project GitHub link

error screenshot

IB builder screenshot

2 个答案:

答案 0 :(得分:1)

链接项目上有一个open pull request,可以从界面构建器中使用它。为什么不尝试使用该分叉而不是原始的回购?

目前无法正常工作的原因是在init(frame:)方法中正在进行大量设置。从故事板创建对象时,不会调用该方法,而是使用init(coder:)。在上面的代码中,该方法为空,因此没有完成任何设置。

通常,您会将常用设置代码放在单独的方法中,并从两个初始化程序中调用它。这不是PR作者所采取的方法,但你可以随时自己动手。

举个例子:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override init(frame: CGRect) {
    super.init(frame: frame)

    self.top.path = shortStroke
    self.middle.path = outline
    self.bottom.path = shortStroke
    // plus all the other code in here...
}

会变成:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.commonSetUp()
}

override init(frame: CGRect) {
    super.init(frame: frame)
    self.commonSetUp()
}

private func commonSetUp() {
    self.top.path = shortStroke
    self.middle.path = outline
    self.bottom.path = shortStroke
    // plus all the other code in here...
}

答案 1 :(得分:0)

您可以尝试将#selector(serchViewController.toggle(_:))更改为#selector(toggle(_:))吗?看起来它正在寻找nil,因为您正试图将其指向class func。您已在方法中说明您的目标是self,它应该指向method current中的instance