从Swift中的另一个类访问ViewController中的对象

时间:2016-02-10 16:01:22

标签: ios swift class uiview uiviewcontroller

我有一个ViewController,其中包含名为myView的UIView和名为myImageView的UIImageView。在下面的代码中,我有一个名为viewLine的类,它附加到名为myView的UIView。

我遇到的麻烦是调用touchesEnded时,我想在ViewController中更改myImageView的alpha。当我尝试这个时,myImageView的alpha值没有变化。

(或者,当我尝试通过将viewLine类移动到主ViewController中来实现此目的时,会出现以下错误 - override func drawRect(rect: CGRect) - Method不会覆盖其超类中的任何方法< / em>和self.setNeedsDisplay() - “ViewController”类型的值没有成员'setNeedsDisplay'。)

问题:

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

2 - 我在ViewController中有一个滑块sliderLineSize,在ViewController中有一个变量lineSize。 UISlider sliderLineSize更改lineSize。但是,lineSize类的drawRect部分使用了viewLine。 如何传递或访问类中ViewController中的变量集?

(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()
    }

}

1 个答案:

答案 0 :(得分:2)

我查看了如何从其子视图引用ViewController,我发现最好的赌注是StackOverflow回答说&#34;遵循MVC模式,ViewController知道它的视图,但视图不应该是了解ViewController。相反,你应该声明委托协议&#34; (来源:Swift - How to pass a view controller's reference to a sub UIView class?

所以,我的解决方案是编写自定义委托协议并使ViewController遵守它。上述答案中的代码有点过时,无法编写委托协议,但Pure Swift class conforming to protocol with static method - issue with upcasting中问题的开头显示了如何正确编写适用于我的Xcode 7.2的协议。

我的故事板上有这样的图表:

  • 查看
    • 我的观点(链接到您的代码)
    • 我的图像视图(背景是我选择的静态图像)

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

代码:

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()
    }

}

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