UITapGesture doesn't work as expected on Popup class - ios

I create a Popup class to use in my app and I want to add a UITapGestureRecognizer to the black layer opacity, when the user touch outside of the popup this close automatically. But the gesture was not recognized. I show you my code of the Popup class
class Popup {
let supView : UIView!
let blackVoile = UIView()
init(superView viewToInsert : UIView){
self.supView = viewToInsert
build()
}
private func build(){
blackVoile.frame = supView.bounds
blackVoile.layer.backgroundColor = UIColor.black.cgColor
blackVoile.isUserInteractionEnabled = true
let closeGesture = UITapGestureRecognizer(target: self, action: #selector(self.close))
blackVoile.addGestureRecognizer(closeGesture)
}
func show(){
supView.addSubview(blackVoile)
}
#objc func close(){
print("close function")
self.blackVoile.removeFromSuperview()
}
}
The close func was never called. And there is no other over layer above the blackVoile UIView
This is when I called my class :
let newPopup = Popup(superView : self.view)
newPopup.show()
I'm beginner so, maybe we can't add gesture to a class who are not have an UIView instance?

Problem with your opacity. If we make any opacity to zero then that view consider as a hidden. So, your tapGesture not working.
Update
var newPopup : Popup!
override func viewDidLoad() {
super.viewDidLoad()
newPopup = Popup(superView : self.view)
newPopup.show()
}

Your supView also needs to be userInteractionEnabled.

Related

iOS Swift: Send action (control event) from subclass of UIImageView

How can I send action (similar kind of tap event) from sub class of UIImageView to View Controller.
Here is reference answer, that I want to apply for UIImageView. (UIImageView does not have UIControl in its super class hierarchy)
Following is my code but not working as I don't know, how to implement, what I need.
class TappableImageView: UIImageView {
// Initializer methods.....
//------------------------------------------
private func addTapGesture(){
let tapOnImage = UITapGestureRecognizer(target: self, action: #selector(TappableImageView.handleTapGesture(tapGesture:)))
self.isUserInteractionEnabled = true
self.addGestureRecognizer(tapOnImage)
}
//----------------------------------------------
#objc func handleTapGesture(tapGesture: UITapGestureRecognizer) {
// how can I send tap/click event to all view controllers, where I've used this image from this point.
}
}
Is there any alternate/other solution that may work for me?
I will recommend you to use a closure to handle taps:
class TappableImageView: UIImageView {
var handleTap: (() -> Void)? = nil
//------------------------------------------
private func addTapGesture(){
let tapOnImage = UITapGestureRecognizer(target: self, action: #selector(TappableImageView.handleTapGesture(tapGesture:)))
self.isUserInteractionEnabled = true
self.addGestureRecognizer(tapOnImage)
}
//----------------------------------------------
#objc func handleTapGesture(tapGesture: UITapGestureRecognizer) {
handleTap?()
}
}
And then I your view controller you can use this i.e. in viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
yourTappableImageView.handleTap = {
print("an image view was tapped")
}
}
It assumes that your TappableImageView is stored in variable named yourTappableImageView.

UIGestureRecognizer on only one part of the screen

If you look into the image, you'll see a textview, button and a slider.
I have completed all the steps except for the last one which is, when I tap on the slider, it constantly disappear. I know it disappear because I implemented UITapGestureRecognizer.
I guess my question is, I want the slider to disappear everytime I tap anywhere on the screen but when I am using the slider, I dont want the slider to disappear which is happening now every time I release my tap.
I have tried implementing one more UITapGestureRecognizer in sizeRefont with a function to keep sizeRefont.isHidden false but when I do that, the slider will not disappear whenever I tap on the screen.
I tried putting sizeRefont.isHidden = false in sizeRefont action and it doesnt work either.
class ResizeController: UIViewController {
#IBOutlet weak var sizeRefont: UISlider!
#IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissRefontSize(_:)))
view.addGestureRecognizer(tap)
}
#IBAction func sizeRefont(_ sender: AnyObject) {
let fontSize = CGFloat(sizeRefont.value)
textView.font = UIFont(name: textView.font!.fontName, size: fontSize * 30.0)
}
#IBAction func showSlider(_ sender: Any) {
sizeRefont.isHidden = false
}
func dismissRefontSize(_ sender: UITapGestureRecognizer) {
if sender.location(in: sizeRefont){
sizeRefont.isHidden = false
} else {
sizeRefont.isHidden = true
}
}
}
There is an error on if sender.location(in: sizeRefont) where it says CGPoint is not convertible to Bool
Image
First thing you need to do is you need to Adjust the dismissRefontSize() method to to the following :
func dismissRefontSize(_ sender: UITapGestureRecognizer) {
let location = sender.location(in: view)
If sizeReFont.frame.contains(location) {
// do nothing
}else {
sizeReFont.isHidden = true
}
}
The other thing you need to adjust is creating the tap recognized in your viewDidLoad() to the following:
let tap = UITapGestureRecognizer(target: self, action : #selector(dismissRefontSize(_:)))

UITapGestureRecognizer not working inside of custom class (that's not a view controller)

I have a custom class Overlay where I added UIButton. When the button is clicked, a method should be called:
class Overlay {
func show(onView view: UIView, frame: CGRect) {
let dismissButton = UIButton()
dismissButton.frame = frame
dismissButton.setTitle("Dismiss", for: .normal)
dismissButton.setTitleColor(Project.Color.failure, for: .normal)
dismissButton.titleLabel?.font = Project.Typography.lightFont.withSize(22)
view.addSubview(dismissButton)
dismissButton.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissBtnTapped(tap:)))
dismissButton.addGestureRecognizer(tap)
}
#objc func dismissBtnTapped(tap: UITapGestureRecognizer) {
print("TEST")
}
I call show(...) inside my ViewController, passing in its view and a frame.
But the tapGestrueRecognizer is not working. Any ideas?
Thank you.
Edit: I tried putting this code directly inside my ViewController. Then it works. I'm not sure why, though, and that's not a viable solution for me, unfortunately :/
Edit 2:
That's how I call it:
let overlay = Overlay()
overlay.show(onView: self.view, frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 150))
You are already adding a button try adding a target to it instead of a gesture,
and make your overlay variable global.
class YourControllerClass: UIViewController {
let overlay = Overlay()
...
func show(onView: UIView, frame: CGRect) {
...
dismissButton.addTarget(self, action: #selector(dismissBtnTapped(_:)), forControlEvents: .TouchUpInside)
}
func dismissBtnTapped(sender:UIButton){
}
}
Hope this helps.
You not need to add tapgesturerecognizer on uibutton, you can directly add target on it something like,
dismissButton.addTarget(self, action: #selector(dismissBtnTapped), forControlEvents: .TouchUpInside)
and remove parameter from dismissBtnTapped method!
Make sure your view which you are passing as onView in show(onView: UIView, frame: CGRect) method is enabled for user interactions.
As an example my script
step 1
class MyIcon {
var targetController = UIViewController()
func show(_ targetController:UIViewController, _ view: UIView, _ frame: CGRect) {
self.targetController = targetController
let icon = UIImageView()
icon.frame = frame
icon.image = UIImage(named: "image_user.png")
icon.isUserInteractionEnabled = true
view.addSubview(icon)
let tap = UITapGestureRecognizer(target: self.targetController, action: #selector(iconTapped))
icon.addGestureRecognizer(tap)
}
#objc func iconTapped(_ icon: UIImageView) {
print("Yo hoo! This worked!")
}
}
step 2
class MyController: UIViewController{
let myicon = MyIcon()
override func viewDidLoad() {
super.viewDidLoad()
myicon.show(self, self.view, self.view.frame)
}
#IBAction func iconTapped(_ icon: UIImageView){
myicon.iconTapped(icon)
}
}
Non of the above solve the problem here.
The point is, if you create the instance of the custom class inside of an event the instance is deleted after the event is completed since it is not associated with any persistent element in your app. Thats why you have to instantiate the object of the class as an attribute of the superview.

GestureRecognizer doesnt work dynamic/in extra class swift

I want to implement a gesture recognizer for every Viewcontroller.
The following code is working:
class ViewController: UIViewController {
func draggedView(sender:UIPanGestureRecognizer){
// do stuff
}
override func viewDidLoad() {
super.viewDidLoad()
let panRec = UIPanGestureRecognizer()
panRec.addTarget(self, action: #selector(ViewController.draggedView(_:)))
self.view.addGestureRecognizer(panRec)
self.view.userInteractionEnabled = true
}
}
Now I want give this pan gesture a little bit more dynamic/abstraction
class Tools : NSObject {
var currentViewController: UIViewController?
func addPanToViewController(viewcontroller: UIViewController) {
currentViewcontroller = viewcontroller
if let currentViewcontroller = currentViewcontroller {
let panRec = UIPanGestureRecognizer()
panRec.addTarget(self, action: #selector(draggedView(_:)))
currentViewcontroller.view.addGestureRecognizer(panRec)
currentViewcontroller.view.userInteractionEnabled = true
}
}
func draggedView(sender:UIPanGestureRecognizer) {
//never called
}
}
I call the code in the ViewController-Class like this:
let sidemenu = Tools()
sidemenu.addPanToViewController(self)
But nothing happens. No Error, but no gestures are working. With the debugger I see that the gesture was added. So every code get executed.
I want execute the draggedView inside my Tools class.
I really don't understand where my problem is?
I think if you want this to work, you have to make the Tools class become singleton with:
static let sharedInstance = Tools()
then in the addPanToViewController:
panRec.addTarget(Tools.sharedInstance, action:#selector(draggedView(_:)))
In your viewController:
Tools.sharedInstance.addPanToViewController(self)
currentViewcontroller.delegete = your gesturerecogniser delegate

UIView tap recognizer not working

Trying to make work tap recognition on a UIView:
#IBOutlet weak var mapView_: GMSMapView!
#IBOutlet weak var viewInfo: UIView!
override func viewDidLoad() {
super.viewDidLoad()
/* MapView inital values & dependencies */
let initialLocation = CLLocationCoordinate2DMake(37.78, -122.41)
let camera = GMSCameraPosition.cameraWithTarget(initialLocation, zoom: 10)
/* Set up MapView */
mapView_.camera = camera
mapView_.myLocationEnabled = true
mapView_.delegate = self
var selfTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "viewTapped:")
viewInfo.addGestureRecognizer(selfTap)
viewInfo.userInteractionEnabled = true
mapView_.insertSubview(viewInfo, aboveSubview: mapView_)
}
func viewTapped(recognizer: UIGestureRecognizer) -> Void{
NSLog("tapped")
}
It doesn't recognize the tap.
Any idea ?
Thanks
Problem "solved"
The problem occurred due to the viewInfo being a subView of googlemaps view.
I couldn't delegate tap event to viewcontroller, so I assumed the event "tap" was being sending to mapview.
I took out the viewInfo from mapview and played a little with constraints to place where I wanted it. So the parent of viewInfo now is viewcontroller and the tap event is recognized without any problem.
I guess this is not the better solution as we need to be very careful when moving the subview in the storyboard to not let it becomes part of mapview, but for while I can't figure out how delegate the subview to viewcontroller.
Thank you all for your help.
You need to remove the : from handleTap: or you need to change your method to handleTap(sender: UITapGestureRecognizer)
use:
func handleTap(sender: UITapGestureRecognizer) {
NSLog("tapped")
}

Resources