I have the following code:
class SegmentedControlViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var happyOutlet: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
scrollView?.delegate = self
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.x > 490 {
happyOutlet?.imageView?.tintColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1)
}
else {
print("nope")
}
}
@IBAction func happy(_ sender: UIButton) {
happyOutlet.imageView?.tintColor = #colorLiteral(red: 0.9294117647, green: 0.4705882353, blue: 0.07450980392, alpha: 1)
}
}
When I click the button the image tint color changes, although when I scroll more than 450 the tint color doesn't change. I know that my code is right because inside the if
statement I tried printing something and it worked so it's something with the button outlet I guess. Also unless I unwrap the happyOutlet in the if statement I get the unwrap optional is nil error.
EDIT
I changed my func to this:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.x > 20 {
print("greater than 20")
happyOutlet?.imageView?.tintColor = .red
}
else {
print("less than 21")
happyOutlet?.imageView?.tintColor = .green
}
}
Although still same thing just the color isn't changing at all, although the stuff gets printed to the console. Also if I don't add the question marks I get the error. What am I doing wrong?
Edit 2
Take a look at: https://github.com/DonMag/DidScrollTest
Simple example, plus your project with lots of edits.
Edit
After getting more detail and looking at your sample project...
You have an instance of SegmentedControlViewController
which uses a UIContainerView
to load your "scroll view" controller. However, your have also assign SegmentedControlViewController
as the class for that controller.
The two controllers in your Storyboard have different elements connected via @IBOutlet
. This will not work (as you have seen).
To accomplish your design, you need a different class for your "scroll view" controller, and you'll want to use a custom delegate / protocol pattern to communicate between them.
As a side note: It would serve you well to learn some of the fundamentals.
In a number of places in your code, you use:
happyView?.alpha = 1
However, that ?
means:
If the variable preceding it is Nil, DON'T do what comes after it.
So, you're avoiding nil
errors by telling the code not to execute, but that doesn't help when you want it to execute.
When you write this:
happyView.alpha = 1
and your app crashes with Unexpectedly found nil...
, you need to fix that - not edit your code to ignore it.
Assuming:
@IBOutlet var scrollView: UIScrollView!
@IBOutlet var happyOutlet: UIButton!
This will change the tint color of the button's image view between red and green, as you scroll 20-pts left and back right. As you scroll, it will also print()
the scroll view's content offset x and a message whether it is greater than or less than 20:
class SegmentedControlViewController: UIViewController {
@IBOutlet var scrollView: UIScrollView!
@IBOutlet var happyOutlet: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// assign the delegate
scrollView.delegate = self
}
}
extension SegmentedControlViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("content offset x:", scrollView.contentOffset.x)
// if we've scrolled left more than 20 points
if scrollView.contentOffset.x > 20 {
print("greater than 20")
happyOutlet.imageView?.tintColor = .red
}
else {
print("less than 21")
happyOutlet.imageView?.tintColor = .green
}
}
}
Note:
If the happyOutlet
button is a subview of the scroll view, in case it's not obvious, the button must be more than 20-pts from the leading edge of the scroll view... otherwise you won't see it change when it is scrolled out of view.