Cannot find "self" in scope & Consecutive declarations on a line must be separated by ";".

I have the following GestureManager class that I want to use to clean up the ViewController where the GestureRecognizer functionality is going to be happening.
class GestureManager {
var vc: UIViewController?
Code Block
@objc func respondToSwipeGesture(_ gesture : UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case .right:
print("swiped right!")
case .left:
print("Swiped left")
case .up:
print("Swiped up")
case .down:
print("Swiped down")
default:
return
}
}
}
let rightSwipe = UISwipeGestureRecognizer(target: self.vc, action: #selector(respondToSwipeGesture(_:)))
rightSwipe.direction = .right
let leftSwipe = UISwipeGestureRecognizer(target: self.vc, action: #selector(respondToSwipeGesture(_:)))
leftSwipe.direction = .left
}
But I would get the following errors in the above variables (rightSwipe, leftSwipe)
Code Block
Cannot find "self" in scope

Code Block
Consecutive declarations on a line must be separated by ";"

Why is this happening? I'm expecting to pass the ViewController to be used in the "target" attribute, but why self cannot be found in scope? Isn't SELF supposed to be pointing to GestureManager class?
This is probably a basic question, but I'm still on they of learning the basics of swift, classes, the different methods etc.
Thanks in advance!

Isn't SELF supposed to be pointing to GestureManager class?

Yes it is… But …

Code Block
let rightSwipe = UISwipeGestureRecognizer(target: self.vc, action: #selector(respondToSwipeGesture(_:)))
rightSwipe.direction = .right
let leftSwipe = UISwipeGestureRecognizer(target: self.vc, action: #selector(respondToSwipeGesture(_:)))
leftSwipe.direction = .left


This code should be inside a func (like viewDidLoad), not free floating in the class, where it is looked at as a declaration.

So you should have:

Code Block
override func viewDidLoad() {
super.viewDidLoad()
let rightSwipe = UISwipeGestureRecognizer(target: self.vc, action: #selector(respondToSwipeGesture(_:)))
rightSwipe.direction = .right
let leftSwipe = UISwipeGestureRecognizer(target: self.vc, action: #selector(respondToSwipeGesture(_:)))
leftSwipe.direction = .left
}

Why is this happening?

Because you are using self in the initial values of instance property declaration.
And you are writing executable statements where they are not allowed.

why self cannot be found in scope? 

You cannot use self in the initial values of instance property declaration in Swift.

Isn't SELF supposed to be pointing to GestureManager class?

Swift utilizes case-sensitive identifiers. You should better care about letter cases. If you want some words to be emphasized, you can use some markdown features.


But the most critically bad thins is this one:

 I'm expecting to pass the ViewController to be used in the "target" attribute

When you use target-action pattern, the target and the action needs to be consistent.
If you pass self.vc to target:, you need to pass an instance method of self.vc to action:.


The right fix may depend on the usage of the class GestureManager, but one possible fix would be something like this:
Code Block
class GestureManager {
var vc: UIViewController?
@objc func respondToSwipeGesture(_ gesture : UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case .right:
print("swiped right!")
case .left:
print("Swiped left")
case .up:
print("Swiped up")
case .down:
print("Swiped down")
default:
return
}
}
}
lazy var rightSwipe: UISwipeGestureRecognizer = {
let rightSwipeGR = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(_:)))
rightSwipeGR.direction = .right
return rightSwipeGR
}()
lazy var leftSwipe: UISwipeGestureRecognizer = {
let leftSwipeGR = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(_:)))
leftSwipeGR.direction = .left
return leftSwipeGR
}()
}

  • You can use self in the initial values of lazy instance property.

  • To run some executable statement like rightSwipe.direction = .right, you need to create a function and call it.

  • If you do want to call the method respondToSwipeGesture(_:) of GestureManager, the target needs to be self, not self.vc.

If you are not accustomed to utilizing closure, you can define explicit functions:
Code Block
lazy var rightSwipe: UISwipeGestureRecognizer = createRightSwipeGR()
private func createRightSwipeGR() -> UISwipeGestureRecognizer {
let rightSwipeGR = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(_:)))
rightSwipeGR.direction = .right
return rightSwipeGR
}
lazy var leftSwipe: UISwipeGestureRecognizer = createLeftSwipeGR()
private func createLeftSwipeGR() -> UISwipeGestureRecognizer {
let leftSwipeGR = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(_:)))
leftSwipeGR.direction = .left
return leftSwipeGR
}


Cannot find "self" in scope & Consecutive declarations on a line must be separated by ";".
 
 
Q