在Swift中从不同的类访问ViewController中的对象

我有一个名为myView的UIView和名为myView的UIImageView的myImageView 。 在下面的代码中,我有一个名为viewLine的类,它连接到名为myView的UIView。

我遇到的麻烦是当touchesEnded被调用时,我想更改ViewController中的myImageView的alpha。 当我尝试这个时,不会更改myImageView的alpha。

(或者,当我尝试通过将viewLine类移动到主ViewController来实现这一点,出现以下错误 – override func drawRect(rect: CGRect)方法不会覆盖任何超类的方法 self.setNeedsDisplay()Valuetypes'ViewController'没有成员'setNeedsDisplay' 。)

问题:

1 – 如何修改名为viewLine的类中的代码以访问ViewController故事板上的其他UI对象或函数,如myImageView 即如何在touchesEnded被调用后,从名为viewLine的类中更改myImageView的alpha值?

2 – 我在ViewController中有一个滑块sliderLineSize ,在ViewController中有一个可变的lineSize UISlider sliderLineSize更改lineSize 但是, lineSize用于viewLine类的drawRect部分。 如何传递或访问类中的ViewController中设置的variables?

(3 – 如何将viewLine类并入主ViewController?)

 import UIKit class ViewController: UIViewController { @IBOutlet weak var myView: UIView! @IBOutlet weak var myImageView: UIImageView! var lineSize: Int = 1 override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { myImageView.alpha = 0.5 } @IBAction func sliderLineSize(sender: UISlider) { lineSize = Int(sender.value) } } class viewLine: UIView { let path=UIBezierPath() var incrementalImage:UIImage? var previousPoint:CGPoint = CGPoint.zero var strokeColor:UIColor? required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func drawRect(rect: CGRect) { incrementalImage?.drawInRect(rect) path.lineWidth = lineSize path.stroke() } override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { let touch: AnyObject? = touches.first let currentPoint = touch!.locationInView(self) path.moveToPoint(currentPoint) previousPoint=currentPoint self.setNeedsDisplay() } override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { let touch: AnyObject? = touches.first let currentPoint = touch!.locationInView(self) let midPoint = self.midPoint(previousPoint, p1: currentPoint) path.addQuadCurveToPoint(midPoint,controlPoint: previousPoint) previousPoint=currentPoint path.moveToPoint(midPoint) self.setNeedsDisplay() } override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { self.drawBitmap() self.setNeedsDisplay() path.removeAllPoints() } func midPoint(p0:CGPoint,p1:CGPoint)->CGPoint { let x=(p0.x+p1.x)/2 let y=(p0.y+p1.y)/2 return CGPoint(x: x, y: y) } func drawBitmap() { UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 1) strokeColor?.setStroke() if((incrementalImage) == nil){ let rectPath:UIBezierPath = UIBezierPath(rect: self.bounds) UIColor.whiteColor().setFill() rectPath.fill() } incrementalImage?.drawAtPoint(CGPointZero) path.stroke() incrementalImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() } } 

我查了一下如何从它的子视图引用一个ViewController,我发现最好的select是一个StackOverflow的答案:“遵循MVC模式,ViewController知道它的Views,但View不应该知道ViewController。声明委托协议“(来源: Swift的 – 如何传递一个视图控制器的引用到一个子UIView类? )

所以,我虽然解决scheme是编写一个自定义的委托协议,使ViewController遵守它。 前面提到的答案中的代码已经有点过时了,但是在Pure Swift类中,问题的开始符合静态方法的协议 – 上传问题展示了如何正确编写一个适用于我的Xcode 7.2的协议。

我的故事板有这样一个图表:

  • 视图
    • 我的视图(链接到您的代码)
    • 我的图片视图(背景是我select的静态图片)

我将类viewLine重命名为viewLine ,因为我认为它将是底层超类的更具描述性的名称。 代码如下。

码:

 import UIKit protocol ViewLineUIViewDelegate: class { func onTouchesEnded(viewLine: ViewLineUIView) } class ViewController: UIViewController, ViewLineUIViewDelegate { @IBOutlet weak var myView: UIView! @IBOutlet weak var myImageView: UIImageView! @IBOutlet weak var sliderValue: UISlider! var viewLineDelegate: ViewLineUIView! override func viewDidLoad() { super.viewDidLoad() viewLineDelegate = myView as? ViewLineUIView viewLineDelegate!.delegate = self //update lineWidth to initial value of slider updateLineWidth() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func onTouchesEnded(viewLine: ViewLineUIView) { myImageView!.alpha = 0.5 } //Updating lineWidth! @IBAction func onSliderChange(sender: UISlider) { updateLineWidth() } func updateLineWidth() { let drawView = myView as! ViewLineUIView //you can change this "10" value to your max lineWidth drawView.path.lineWidth = CGFloat(sliderValue.value*10) print("New value is: " + String(drawView.path.lineWidth)) } } class ViewLineUIView: UIView { weak var delegate: ViewLineUIViewDelegate? let path=UIBezierPath() var incrementalImage:UIImage? var previousPoint:CGPoint = CGPoint.zero var strokeColor:UIColor? required init?(coder aDecoder: NSCoder) { //Initialize lineWidth so that compiler doesn't complain super.init(coder: aDecoder) } override func drawRect(rect: CGRect) { incrementalImage?.drawInRect(rect) path.stroke() } override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { let touch: AnyObject? = touches.first let currentPoint = touch!.locationInView(self) path.moveToPoint(currentPoint) previousPoint=currentPoint self.setNeedsDisplay() } override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { let touch: AnyObject? = touches.first let currentPoint = touch!.locationInView(self) let midPoint = self.midPoint(previousPoint, p1: currentPoint) path.addQuadCurveToPoint(midPoint,controlPoint: previousPoint) previousPoint=currentPoint path.moveToPoint(midPoint) self.setNeedsDisplay() } override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { self.drawBitmap() self.setNeedsDisplay() path.removeAllPoints() delegate?.onTouchesEnded(self) } func midPoint(p0:CGPoint,p1:CGPoint)->CGPoint { let x=(p0.x+p1.x)/2 let y=(p0.y+p1.y)/2 return CGPoint(x: x, y: y) } func drawBitmap() { UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 1) strokeColor?.setStroke() if((incrementalImage) == nil){ let rectPath:UIBezierPath = UIBezierPath(rect: self.bounds) UIColor.whiteColor().setFill() rectPath.fill() } incrementalImage?.drawAtPoint(CGPointZero) path.stroke() incrementalImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() } } 

如您所见,编辑path的lineWidth非常简单,您不需要创build另一个委托协议。 ViewController可以直接访问它的子视图。 你应该知道需要一个演员阵容。