How can I make a clickable UILabel in Swift 3? - ios

I'm trying to make a clickable UILabel by following this code:
class ViewNotificationsDetails: UIViewController {
#IBOutlet weak var back: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(ViewNotificationsDetails.tapFunction))
back.isUserInteractionEnabled = true
back.addGestureRecognizer(tap)
}
#objc func tapFunction(sender:UITapGestureRecognizer) {
print("tap working")
}
}
But when executing the code, I get the error ->
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value on the line "back.isUserInteractionEnabled = true".
What could be the problem?

try this code, is working well with me
class ViewController: UIViewController {
#IBOutlet weak var cliclableLable: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapFunction))
cliclableLable.isUserInteractionEnabled = true
cliclableLable.addGestureRecognizer(tap)
}
func tapFunction(sender:UITapGestureRecognizer) {
print("tap working")
}
}
also don't forget to link your label with the code

Problem is with your Label memory allocation. You have created IBOutlet of label but not connected it with Interface from your Storyboard/XIB view controller.
Go to your Interface Builder: (Storyboard/XIB) View Controller ▶ Select 'Connection Inspector' ▶ Connect label outlet 'back' with Label interface element

Use back.userInteractionEnabled = true
you did wrong as isUserInteractionEnabled.

Add a UIButton element on the label. clear button placeholder, make button constraints equal to the label i.e equal height, equal width, Top, bottom. In the above image, label has only trailing fixed as it expands wrt text. so button trailing should be to trailing to the label. No leading constraint to the button in the below context. Finally created an IBAction and write your code to get your task done.

Related

IOS Swift TextView UITapGestureRecognizer with tab to move cursor

i used default keyboard and custom keyboard
if textview touch event when custom keyboard is showing, change to default keyboard
class ReplyPage: UIViewController ,UITextViewDelegate,EmojiKeyboardDelegate,UIGestureRecognizerDelegate{
#IBOutlet weak var replyArea: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
replyArea.delegate=self
emojiView.delegate = self
replyPage = self
let tapTerm = UITapGestureRecognizer(target: self, action: #selector(textViewTouch))
tapTerm.delegate = self
replyArea.addGestureRecognizer(tapTerm)
more code...
}
#objc func textViewTouch(){
if isEmoji{
replyArea.inputView = nil
replyArea.reloadInputViews()
isEmoji = false
emojiButton.setImage(UIImage(named:"emoji"), for: UIControlState.normal)
}else{
replyArea.reloadInputViews()
replyArea.becomeFirstResponder()
}
}
}
this code is worked
but can't move cursor in textview
default tab is move cursor
but UITapGesture override this so can't work
how to use Both default tab and UITapGesture
Can i Listen Textview Touch without UITapGesture?
can't textViewDidBeginEditing()
TextView Tap do not call textViewDidBeginEditing after first open custom keyboard.
because First Custom Keyboard Open already call textViewDidBeginEditing
Please add protocol TextViewDelegate in your viewController .
And add
self.replyArea.delegate = self

Tap gesture recognizer added to UILabel not working

I've the following code to add a gesture recognizer to a UILabel. User Interaction Enabled is ticked on for the label in the storyboard, but when I tap on the label the onUserClickingSendToken method is not being called.
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
#IBOutlet weak var tokenDisplay: UILabel!
var tapGestureRecognizer:UITapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(onUserClickingSendToken(_:)))
override func viewDidLoad() {
super.viewDidLoad()
tapGestureRecognizer.numberOfTapsRequired = 1
tokenDisplay.addGestureRecognizer(tapGestureRecognizer)
}
func onUserClickingSendToken(_ sender: Any)
{
....
Initializing the tapRecognizer in viewDidLoad should do it, cause you were targeting self before the view was initialized
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
#IBOutlet weak var tokenDisplay: UILabel!
var tapGestureRecognizer:UITapGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
tapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(onUserClickingSendToken(_:)))
tapGestureRecognizer.numberOfTapsRequired = 1
tokenDisplay.isUserInteractionEnabled = true
tokenDisplay.addGestureRecognizer(tapGestureRecognizer)
}
#objc func onUserClickingSendToken(_ sender: Any)
{
....
In general for UILabel clickable issue:
There are couple of reasons why your UILabel will not work as clickable
Make sure to mark UILabel UserInteraction true and if yourLabel is inside other view than mark that view UserInteraction true too.
yourLabel.isUserInteractionEnabled = true
Assigning self to target before the view initialisation, move your code inside viewDidLoad/awakeFromNib or after view Load
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.yourLabel.addGestureRecognizer(tap)
If you are adding UILabel programmatically, than you have to assign it's frame too.
yourLabel.frame = CGRect(x: 0, y: 0, width: 300, height: 20)
Super view in which your UILabel is should be large enough to fit/display label properly, if your label is inside some view than that view's height/weight should assign in a way that it cover the whole UILabel frame.
In my case this was the problem I had, I tried so many thing but at last it turns out that the view in which I had my label had fixed width, the label was displaying properly but onClick event was't working due to out of frame.
It was missing UILabel's trailing constraints, so half of the thing is not clickable.
Using same tab gesture for multiple view, you cannot use one tab gesture for more than one view or labels,use different for each UILabel.
try this:
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.yourLabel.isUserInteractionEnabled = true
self.yourLabel.addGestureRecognizer(tap)
let tap2 = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.someView.isUserInteractionEnabled = true
self.someView.addGestureRecognizer(tap2)
instead of this:
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickLabel(_:)))
self.yourLabel.isUserInteractionEnabled = true
self.yourLabel.addGestureRecognizer(tap)
self.someView.isUserInteractionEnabled = true
self.someView.addGestureRecognizer(tap)
// tapGesture will work on only one element
Try changing your selector setup to:
#selector(ViewController .onUserClickingSendToken(_:).

Ios Swift programatically change view order over storyboard

I have a textView and an imageView added in storyboard as shown in the screenshot below.
In story board order is:
textView
imageView
Now in run imageView covers textView and things assigned to textView does not work.
So I programmatically want to change the order to:
imageView
textView
(Without touching storyboard)
I tried:
self.view.bringSubviewToFront(textView)
self.view.sendSubviewToBack(imageView)
and
imageView.layer.zPosition = 1
textView.layer.zPosition = 2
None of these is working for me
I guess the problem is you might be using these codes in viewDidLoad method. Try using in viewDidAppear
Or another try is using performSelector
write this in viewDidLoad or viewWillAppear
self.performSelector(#selector(changeOrder), withObject: nil, afterDelay: 0.2)
and write your order changing in this function
func changeOrder() {
imageView.layer.zPosition = 1
textView.layer.zPosition = 2
}
Edit
I have made a sample. Have a look.
https://github.com/RajanMaheshwari/OrderingLayer
I have tried the code and its working fine
class ViewController: UIViewController {
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.performSelector(#selector(changeOrder), withObject: nil, afterDelay: 0.2)
}
func changeOrder() {
myImageView.layer.zPosition = 1
myTextField.layer.zPosition = 2
}
}
My Storyboard
My Final Outcome after running the code
Now imageView is on layer 1 and textField is on layer 2 position
If you comment out the performSelector line then the outcome will be
Here the imageView is on layer 2 position and textField is on layer 1 position.

iOS Custom .xib view button tap detect in view controller (Swift)

So I am using a custom View (.xib) which contains couple of objects: UIImage view & UIButton. The custom view in contained and used in View controller UIView , however I can't seem to figure out how to detect if the button(from .xib) is tapped and launch a function in the view controller. Any suggestions?
I can However add UITap gesture to the entire Viewcontroller UIView, however Thats not what i need.
#IBAction func calculateTapped(sender : AnyObject) {
//You can get action here
}
Step 1
Link Your all button to to xib cocoa class
class DialogHandler: UIView {
#IBOutlet weak var acceptBtn: UIButton!
#IBOutlet weak var closeBtn: UIButton!
}
step 2
Add Below code in viewDidLoad()
if let customView = Bundle.main.loadNibNamed("DialogDemo", owner: self, options: nil)?.first as? DialogHandler {
dialogView = customView
customView.acceptBtn.addTarget(self, action: #selector(ViewController.acceptBtnPressed(sender:)), for: .touchUpInside)
}
step 3
Create Function for Button that can handle your click event
#objc func acceptBtnPressed (sender:UIButton) { print("Button Pressed") }

Click button in a UIViewController that was loaded a subView (UIView)

I'm trying to add a UIView subview into a UIViewController, and that UIView has a UISwitch that I want the user to be able to toggle. Based on the state, a UITextField's value will toggle back and forth. Here is the subview (InitialView):
import UIKit
class InitialView: UIView {
// All UI elements.
var yourZipCodeSwitch: UISwitch = UISwitch(frame: CGRectMake(UIScreen.mainScreen().bounds.width/2 + 90, UIScreen.mainScreen().bounds.height/2-115, 0, 0))
override func didMoveToSuperview() {
self.backgroundColor = UIColor.whiteColor()
yourZipCodeSwitch.setOn(true, animated: true)
yourZipCodeSwitch.addTarget(ViewController(), action: "yourZipCodeSwitchPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.addSubview(yourZipCodeSwitch)
}
}
If I want to have it's target properly pointing at the below function, where should I either set the target or include this function? I tried:
Setting the target in the UIViewController instead of the UIView
Keeping the function in the UIView
Here's the function:
// Enable/disable "Current Location" feature for Your Location.
func yourZipCodeSwitchPressed(sender: AnyObject) {
if yourZipCodeSwitch.on
{
yourTemp = yourZipCode.text
yourZipCode.text = "Current Location"
yourZipCode.enabled = false
}
else
{
yourZipCode.text = yourTemp
yourZipCode.enabled = true
}
}
And here is where I'm loading it into the UIViewController:
// add initial view
var initView : InitialView = InitialView()
// Execute on view load
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
view.addSubview(initView)
}
Any help is much appreciated - thanks!
Yeah, the didMoveToSuperView() placement doesn't make much sense. So you're creating a random, totally unconnected ViewController instance to make the compiler happy but your project sad. Control code goes in controllers, view code goes in views.
You need in your real ViewController:
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(initView)
// Note 'self' is the UIViewController here, so we got the scoping right
initView.yourZipCodeSwitch.addTarget(self, action: "yourZipCodeSwitchPressed:", forControlEvents: .ValueChanged)
}
Also, .TouchUpInside is for UIButtons. Toggle switches are much more complicated, so their events are different. Touching up inside on a toggle switch's current setting can and should do nothing, whereas touchup inside on the opposite setting triggers the control event above. iOS does all the internal hit detection for you.

Resources