0

I want to reference a variable to a specific function. However, there is an error called Value of type 'UIView' has no member 'lineTo' Clearly, the whatSelectObject variable contains the classes in which a member exists. So I used If statement, "optional binding." But the results are the same.

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class ObjectView: UIView {
    var outGoingLine : CAShapeLayer?
    var inComingLine : CAShapeLayer?

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

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func lineTo(connectToObj: ObjectView) -> CAShapeLayer {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: self.frame.maxX, y: self.frame.midY))
        path.addLine(to: CGPoint(x: connectToObj.frame.minX, y: connectToObj.frame.midY))

        let line = CAShapeLayer()
        line.path = path.cgPath
        line.lineWidth = 5
        line.fillColor = UIColor.clear.cgColor
        line.strokeColor = UIColor.gray.cgColor
        connectToObj.inComingLine = line
        outGoingLine = line
        return line
    }
}


class MyViewController : UIViewController {
    var whatSelectView: UIView?
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let object = ObjectView(frame: CGRect(x: 10, y: 100, width: 100, height: 100))
        object.backgroundColor = UIColor.orange
        view.addSubview(object)

        whatSelectView = object

        let object2 = ObjectView(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
        object2.backgroundColor = UIColor.red
        view.addSubview(object2)

        if let s = whatSelectView {
            view.layer.addSublayer(s.lineTo(connectToObj: object2)) // error
        }

        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

!This code is an example of a reduced code in question to help the respondent understand it. I can refer directly to the object variable, but I must refer to whatSelectView without fail.

Why does cause an error in the reference variable? Or was I wrong with the Optional binding?

bakuiseok
  • 41
  • 1
  • 10
  • `if let s = whatSelectView as? ObjectView` instead of `if let s = whatSelectView`. Because for the compiler `whatSelectView` is a `UIView` (as stated in the error you get), so id doesn't know `lineTo(connectToObj:)`. Tell the compiler with the cast that's if it's in fact a `ObjectView` object, so it knows that method. – Larme Mar 20 '19 at 13:52
  • @Larme Thank you for your first good answer to the question. – bakuiseok Mar 20 '19 at 14:09

3 Answers3

1

Indeed UIView does not have any member nor method called lineTo, and you have to use casting (as? in your case)

like this:

if let s = whatSelectView as? ObjectView {
     view.layer.addSublayer(s.lineTo(connectToObj: object2)) // error
}

Beside that, the reference to whatSelectView should be weak because view already keeps a strong reference to it since it object is a subview.

And you don't need the if condition at all, you already have reference to the view using object.

So, Here is my proposal for better implementation

class MyViewController : UIViewController {
    weak var whatSelectView: ObjectView?

    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let object = ObjectView(frame: CGRect(x: 10, y: 100, width: 100, height: 100))
        object.backgroundColor = UIColor.orange
        view.addSubview(object)

        whatSelectView = object

        let object2 = ObjectView(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
        object2.backgroundColor = UIColor.red
        view.addSubview(object2)

        let shape = object.lineTo(connectToObj: object2)
        view.layer.addSublayer(shape)

        self.view = view
    }
}
Benny Davidovitz
  • 1,152
  • 15
  • 18
0
if let s = whatSelectView as? ObjectView {
   view.layer.addSublayer(s.lineTo(connectToObj: object2))
}

this should resolve your problem.

Omar Chaabouni
  • 448
  • 2
  • 19
0

Change

var whatSelectView: UIView?

to

var whatSelectView: ObjectView?

and it will compile. As @Larme said, when you declare it as a simple UIView, then you can't access any members & functions that are on subclasses of UIView.

NRitH
  • 13,441
  • 4
  • 41
  • 44