Why is my UITapGestureRecognizer not triggering my function for a UIAlertAction? When I build and run my app for the iOS Simulator, my image will not recognize a tap to trigger the alert.
Any suggestions would be appreciated. Thanks, Swift friends!
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let rect = CGRect(x:20,y:20,width:150,height:100)
let imageView = UIImageView(frame:rect)
let image = UIImage(named:"image.png")
imageView.image = image
// imageView.isUserInteractionEnabled = true
self.view.addSubview(imageView)
let guesture = UITapGestureRecognizer(target: self,action:
#selector(ViewController.singleTap))
imageView.addGestureRecognizer(guesture)
}
func singleTap()
{
let alertView = UIAlertController(title: "Heading", message: "Message!", preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertView.addAction(defaultAction)
self.presentViewController(alertView, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Uncommenting this line in your code
// imageView.isUserInteractionEnabled = true.
might work. Add this also
image.multipleTouchEnabled = YES;
tap.numberOfTapsRequired = 1;
Related
I'm trying to show a UIAlertController over a UIButton. The button is of type custom, and I have set the tint color to UIColor.clear, because I don't want any tint color. I've read that setting your UIButton to custom turns off the tint color, but that doesn't work for me. This method works out ok, until I show an alert controller on top.
This is before adding the alert:
This is what it looks like when I show the alert:
There's a clear grey tint color around the UIButton. It does this with any .selected UIButtons. How do I get rid of this tint? I really don't want to make my own button class just to get rid of this.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var starBtn: UIButton!
var selected: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
starBtn.isSelected = selected
starBtn.setImage(UIImage(named: "StarButtonSelected"), for: .selected)
starBtn.setImage(UIImage(named: "StarButtonDeselected"), for: .normal)
starBtn.isHighlighted = false
starBtn.tintColor = UIColor.clear
starBtn.backgroundColor = UIColor.clear
}
#IBAction func starBtnUp(_ sender: Any) {
selected = !selected
starBtn.isSelected = selected
}
#IBAction func showAlertBtnUp(_ sender: Any) {
let shareFileAction = UIAlertAction(title: "Share File", style: .default) { action in
}
let shareWebLink = UIAlertAction(title: "Share Link", style: .default) { action in
}
let alert = UIAlertController(title: "Share", message: "What do you want to share?", preferredStyle: .alert)
alert.addAction(shareFileAction)
alert.addAction(shareWebLink)
self.present(alert, animated: true) {
}
}
}
Edit: Okay, so if I create the button programmatically only, without using IB, it doesn't do the grey tint thing. I really don't want to have to not use IB though. Here's the re-written code that works how I want it to.
class ViewController: UIViewController {
var starBtn: UIButton!
var selected: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
starBtn = UIButton(type: .custom)
self.view.addSubview(starBtn)
starBtn.translatesAutoresizingMaskIntoConstraints = false
starBtn.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
starBtn.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
starBtn.heightAnchor.constraint(equalToConstant: 60).isActive = true
starBtn.widthAnchor.constraint(equalToConstant: 60).isActive = true
starBtn.isSelected = selected
starBtn.tintColor = UIColor.clear
starBtn.setImage(UIImage(named: "StarButtonSelected"), for: .selected)
starBtn.setImage(UIImage(named: "StarButtonDeselected"), for: .normal)
starBtn.isHighlighted = false
starBtn.backgroundColor = UIColor.clear
starBtn.addTarget(self, action: #selector(starBtnUp(_:)), for: .touchUpInside)
}
#IBAction func starBtnUp(_ sender: Any) {
selected = !selected
starBtn.isSelected = selected
}
#IBAction func showAlertBtnUp(_ sender: Any) {
let shareFileAction = UIAlertAction(title: "Share File", style: .default) { action in
}
let shareWebLink = UIAlertAction(title: "Share Link", style: .default) { action in
}
let alert = UIAlertController(title: "Share", message: "What do you want to share?", preferredStyle: .actionSheet)
alert.addAction(shareFileAction)
alert.addAction(shareWebLink)
self.present(alert, animated: true) {
}
}
}
I'm stumped. Everything is working except it's not. I can call up the camera interface and take or select a photo yet UIImagePickerControllerDelegate is never being called (I've put two print statements that well, never get printed). Everything is correctly connected in IB, or so I believe it is (I'm fully ready for it so be something totally minor that I missed). Anyone care to take a frtesh set of eyes and go over this to see if I just can't see the forest for the trees?
Thanks in advance.
import UIKit
import Foundation
class afterPhotoViewController: UIViewController {
//MARK: - IBOutlet Properties
#IBOutlet weak var afterImageView: UIImageView!
#IBOutlet weak var aftervwImage: UIView!
#IBOutlet weak var cameraBtnPressed: UIButton!
//MARK: - Useful Variables
let afterImagePicker = UIImagePickerController()
var hud = HKProgressHUD()
var localTextFilePath : URL!
var isImageSetted = false
//MARK: - App Delegates
var isMain = false
var originFrame = CGRect()
override func viewDidLoad() {
super.viewDidLoad()
// Init UI Components
self.initUI()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - UI Init
func initUI() {
// Set Navigation Bar
let backButton = UIBarButtonItem(title: "", style: .plain, target: navigationController, action: nil)
navigationItem.leftBarButtonItem = backButton
self.title = "\(h_proposalNumberStr)-\(h_itemIndex)"
// Set ImageView
self.afterImageView.image = #imageLiteral(resourceName: "ic_placeholder")
self.afterImageView.clipsToBounds = false
cameraBtnPressed.layer.cornerRadius = 15
cameraBtnPressed.layer.borderColor = UIColor.lightGray.cgColor
cameraBtnPressed.layer.borderWidth = 1
self.isImageSetted = false
// self.tableView.reloadData()
}
//MARK: - UI Actions
#IBAction func cameraBtnPressed(_ sender: Any) {
//Create the AlertController and add Its action like button in Actionsheet
let actionSheetController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel) { _ in
}
actionSheetController.addAction(cancelActionButton)
let chooseLibraryActionButton = UIAlertAction(title: "Choose from Library", style: .default)
{ _ in
self.isMain = true
self.afterImagePicker.allowsEditing = true
self.afterImagePicker.sourceType = .photoLibrary
self.afterImagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
self.present(self.afterImagePicker, animated: true, completion: nil)
}
actionSheetController.addAction(chooseLibraryActionButton)
let takePhotoActionButton = UIAlertAction(title: "Take a Photo", style: .default)
{ _ in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
self.isMain = true
self.afterImagePicker.allowsEditing = false
self.afterImagePicker.sourceType = .camera
self.afterImagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .camera)!
self.afterImagePicker.showsCameraControls = true
self.present(self.afterImagePicker, animated: true, completion: nil)
} else {
Helper.showMessage(vc: self, title: CONSTANTS.APPINFO.APP_NAME, bodyStr: "No camera available.")
}
}
actionSheetController.addAction(takePhotoActionButton)
self.present(actionSheetController, animated: true, completion: nil)
}
//MARK: - UIImagePickerControllerDelegate
extension afterPhotoViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("called")
dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("called2")
//getting actual image
var image = info[UIImagePickerControllerEditedImage] as? UIImage
if image == nil {
image = info[UIImagePickerControllerOriginalImage] as? UIImage
}
afterImageView.image = image
// Set Imageview Corner Radius
afterImageView.layer.cornerRadius = 5
afterImageView.clipsToBounds = true
self.isImageSetted = true
picker.dismiss(animated: true, completion: nil)
}
}
#raja Kishan caught my stupid simple error of forgetting to set the delegate.
Now, where's the facepalm emoji.
You have to specify that the UIImagePickerController's delegate is self, so that the events are triggered.
In your case:
afterImagePicker.delegate = self
I am trying to add UILabels and other UIView elements on button press and have them act as independent elements but I am having no luck. I can successfully add multiple labels and text fields but when i try to delete them using my gesture recognizer it will only delete the latest UIView element. My full code is posted below. There are two main bugs in my implementation as it is: Creating more than one label or text field at a time causes the gestures to not respond and I can only delete the latest UIView element. Any help is greatly appreciated!
My Model:
import Foundation
import UIKit
class QuizItem: UIViewController{
var alert = UIAlertController()
var labelCountStepper = 0
var tfCountStepper = 0
let gestureRecog = myLongPress(target: self, action: #selector(gestureRecognized(sender:)))
let moveGesture = myPanGesture(target: self, action: #selector(userDragged(gesture:)))
func createLabel(){
var randLabel = UILabel(frame: CGRect(x: 200, y: 200, width: 300, height: 20))
randLabel.isUserInteractionEnabled = true
randLabel.textColor = UIColor .black
randLabel.text = "I am a Test Label"
randLabel.tag = labelCountStepper
gestureRecog.quizItem = randLabel
moveGesture.quizItem = randLabel
randLabel.addGestureRecognizer(self.longPressGesture())
randLabel.addGestureRecognizer(self.movePanGesture())
topViewController()?.view.addSubview(randLabel)
labelCountStepper = labelCountStepper+1
}
func createTextField(){
var randTextField = UITextField(frame: CGRect(x: 200, y: 200, width: 300, height: 35))
randTextField.isUserInteractionEnabled = true
randTextField.backgroundColor = UIColor .lightGray
randTextField.placeholder = "Enter your message..."
randTextField.tag = tfCountStepper
gestureRecog.quizItem = randTextField
moveGesture.quizItem = randTextField
randTextField.addGestureRecognizer(self.longPressGesture())
randTextField.addGestureRecognizer(self.movePanGesture())
topViewController()?.view.addSubview(randTextField)
tfCountStepper = tfCountStepper+1
}
func longPressGesture() -> UILongPressGestureRecognizer {
let lpg = UILongPressGestureRecognizer(target: self, action: #selector(gestureRecognized(sender:)))
lpg.minimumPressDuration = 0.5
return lpg
}
func movePanGesture() -> UIPanGestureRecognizer {
let mpg = UIPanGestureRecognizer(target: self, action: #selector(userDragged(gesture:)))
return mpg
}
#objc func gestureRecognized(sender: UILongPressGestureRecognizer){
if(sender.state == .began){
print("Label Tag #: \(labelCountStepper)")
print("Text Field Tag #: \(tfCountStepper)")
alert = UIAlertController(title: "Remove Item?", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in
self.gestureRecog.quizItem.removeFromSuperview()
}))
alert.addAction(UIAlertAction(title: "No", style: .cancel){(_) in
})
topViewController()?.present(alert, animated: true, completion: nil)
}
}
#objc func userDragged(gesture: UIPanGestureRecognizer){
let loc = gesture.location(in: self.view)
moveGesture.quizItem.center = loc
}
override func viewDidLoad() {
super.viewDidLoad()
}
func topViewController() -> UIViewController? {
guard var topViewController = UIApplication.shared.keyWindow?.rootViewController else { return nil }
while topViewController.presentedViewController != nil {
topViewController = topViewController.presentedViewController!
}
return topViewController
}
}
My ViewController:
import UIKit
class ViewController: UIViewController {
var labelMaker = QuizItem()
#IBAction func createLabel(_ sender: UIButton) {
labelMaker.createLabel()
}
#IBAction func createTextField(_ sender: UIButton) {
labelMaker.createTextField()
}
override func viewDidLoad() {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I also made two subclasses that inherit from UILongPress and UIPan Gesture Recognizers. I'll only post the LongPress because the UIPan is exactly the same - just inherits from UIPan instead of UILongPress.
import Foundation
import UIKit
class myLongPress: UILongPressGestureRecognizer{
var quizItem = UIView()
}
You can achieve that by slighting changing your code as below:
#objc func gestureRecognized(sender: UILongPressGestureRecognizer){
if(sender.state == .began){
print("Label Tag #: \(labelCountStepper)")
print("Text Field Tag #: \(tfCountStepper)")
alert = UIAlertController(title: "Remove Item?", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in
let selectedView = sender.view
selectedView?.removeFromSuperview()
}))
alert.addAction(UIAlertAction(title: "No", style: .cancel){(_) in
})
topViewController()?.present(alert, animated: true, completion: nil)
}
}
#objc func userDragged(gesture: UIPanGestureRecognizer){
let loc = gesture.location(in: self.view)
let selectedView = gesture.view
selectedView?.center = loc
}
I have been learning swift for a short time and designed a simple ios swift app in xcode to open up an alert and display the developer name inside of a label when tapped. The code is posted below. For some reason, on the label.hidden = true, I get an error saying "expected declaration", but nothing else. Why is it getting this error message, and what does it mean?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//declares the label
let label = UILabel(frame: CGRectMake(0, 0, 200, 21))
//should hide the label
label.hidden = true
//next 2 lines center the label
label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
//puts text into the label
label.text = "This app was developed by me!"
//declares the function
#IBAction func function() {
// declares variable that stores the alert and it's properties
let alertController = UIAlertController(title: "Welcome!", message: "Here is some information about the developer!", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
label.hidden = false
}
}
You need to encapsulate it with function.
class ViewController: UIViewController {
let label = UILabel(frame: CGRectMake(0, 0, 200, 21))
override func viewDidLoad() {
super.viewDidLoad()
configureViews()
}
func configureViews() {
//declares the label
//should hide the label
label.hidden = true
//next 2 lines center the label
label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
//puts text into the label
label.text = "This app was developed by me!"
}
//declares the function
#IBAction func function() {
// declares variable that stores the alert and it's properties
let alertController = UIAlertController(title: "Welcome!", message: "Here is some information about the developer!", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
label.hidden = false
}
}
I currently have a subview that is created and added to the UIView in ViewDidLoad(). I am attempting to user UIGestureRecognizers to detect a tap and unhide a particular button. My current code:
override func viewDidLoad() {
super.viewDidLoad()
architectView = CustomClass(frame: self.view.bounds)
self.view.addSubview(architectView)
let gestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTap:")
gestureRecognizer.delegate = self
architectView.addGestureRecognizer(gestureRecognizer)
}
func handleTap(gestureRecognizer: UIGestureRecognizer) {
let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
The handleTap() function is a simple test to see if the taps are being recognized. This code does not trigger the UIAlert when it is pressed? What am I missing?
I tested your code here and it does work. However, I think you might be missing to add the UIGestureRecognizerDelegate protocol to your View Controller. See below:
class ViewController: UIViewController, UIGestureRecognizerDelegate {
var architectView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
architectView = UIView(frame: self.view.bounds)
self.view.addSubview(architectView)
let gestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTap:")
gestureRecognizer.delegate = self
architectView.addGestureRecognizer(gestureRecognizer)
}
func handleTap(gestureRecognizer: UIGestureRecognizer) {
let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Swift 3 version code based on Raphael Silva answer:
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
var architectView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
architectView = UIView(frame: self.view.bounds)
self.view.addSubview(architectView)
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(gestureRecognizer:)))
gestureRecognizer.delegate = self
architectView.addGestureRecognizer(gestureRecognizer)
}
func handleTap(gestureRecognizer: UIGestureRecognizer) {
let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}