Beginner question. I have a UISlider on the storyboard, and in another UIView class besides the ViewController I would like to use the slider's value to change path/shape variables within the makeShape() function.
I have tried:
a) In OtherView, try to directly reference ViewController's global variable val
. This results in "unresolved identifier"
b) In ViewController, try to assign mySlider.value
to a variable declared in OtherView, otherVal
. This results in "Instance member 'otherVal' cannot be used on type 'OtherView'".
Could someone please help me learn how to do this correctly?
ViewController.swift:
class ViewController: UIViewController {
var val: CGFloat = 0.0
@IBOutlet weak var mySlider: UISlider!
@IBOutlet weak var otherView: UIView!
@IBAction func mySliderChanged(_ sender: Any) {
val = CGFloat(mySlider.value)
setOtherVal()
}
func setOtherVal() {
otherView.otherVal = val
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let otherView = OtherView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 100, height: 100)))
self.view.addSubview(otherView)
}
}
OtherView.swift:
class OtherView: UIView {
var path: UIBezierPath!
var otherVal: CGFloat = 0.0
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clear
makeShape()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func makeShape() {
let width: CGFloat = self.frame.size.width
let height: CGFloat = self.frame.size.height
let path1 = UIBezierPath(ovalIn: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 50, height: 50)))
let shapeLayer1 = CAShapeLayer()
shapeLayer1.path = path1.cgPath
shapeLayer1.fillColor = UIColor.blue.cgColor
self.layer.addSublayer(shapeLayer1)
shapeLayer1.position = CGPoint(x: otherVal, y: height)
}
}
Right now you're trying to access the otherVal
property in ViewController
on the class OtherVal
which is shared globally through the whole app, not the property on the instance of OtherVal you've created in ViewController
.
The simplest fix here is to store the OtherView
instance you created in viewDidAppear
and use that property to update the view.
class ViewController: UIViewController {
var val: Float = 0.0
@IBOutlet weak var mySlider: UISlider!
// Add a property to hold on to the view after you create it.
var otherView: OtherView?
@IBAction func mySliderChanged(_ sender: Any) {
val = mySlider.value
setOtherVal()
}
func setOtherVal() {
// `val` is a Float and `otherVal` is a `CGFloat` so we have to convert first.
let newValue = CGFloat(self.val)
// Use the property that's holding your view to update with the new value from the slider.
self.otherView?.otherVal = newValue
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let otherView = OtherView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 100, height: 100)))
// Set the property to the view you just created so you can update it later.
self.otherView = otherView
self.view.addSubview(otherView)
}
}
Currently though it doesn't look like you're actually updating OtherView
once the new value is set, so you'll want to do something similar there. Keep a reference to the CAShapeLayer
you create and update the position when otherVal
changes.
Also note viewDidAppear
can be called multiple times throughout a view controller's life cycle. If you only want to add the view once, you should use viewDidLoad
which will guarantee you have a freshly created self.view
to work with.
Edit: As mentioned in the comments, you can also set up a custom view in the storyboard / nib and create an outlet. Right now it doesn't look like your code is set up to work with that though.