有人可以帮我解决这个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!)
}
}
答案 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
。