I want to add target to multiple buttons with sender parameter in Swift but I'm facing a problem
Here's my code
var index = 10
var btn = [UIButton]()
for var i = 0; i<=index; i++
{
btn.append(UIButton(frame : ... ))
btn[i].addTarget(self, action: "event_clicked", forControlEvents: UIControlEvents.TouchUpInside)
}
func event_clicked(sender : UIButton!)
{
sender.backgroundColor = UIColor.whiteColor()
}
it runs well but when I press one of the buttons, the error "libc++abi.dylib: terminating with uncaught exception of type NSException" shows. Please help me with this.
I found the answer by myself. Must write the selecter name "event_name:". Has to put the colon at the end of the selecter name.
Related
I need to add read more at the end of the 3rd line in label.
like this i need:
Note: i have tried this answer Add "...Read More" to the end of UILabel but here read more action is not working and expand collapse also not working.. so tried like below
Actually i need to show description in label.. here if the description if more then 3 lines then i need to show read more at end of the 3rd line and need to expand the label with remaining text..
code: with this code i can expand the label if more than 3 lines but i need to show read more at end of the third line
override func viewDidLoad() {
super.viewDidLoad()
despLbl.text = publicProGenInfo?.result?.user?.description
despLbl.numberOfLines = 3//despLbl.maxNumberOfLines//3
let tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelAction(gesture:)))
despLbl.addGestureRecognizer(tap)
despLbl.isUserInteractionEnabled = true
tap.delegate = self
}
#objc func labelAction(gesture: UITapGestureRecognizer)
{
if despLbl.numberOfLines == 3 {
despLbl.numberOfLines = despLbl.maxNumberOfLines
} else {
despLbl.numberOfLines = 3
}
}
o/p: getting like this.. here after 3rd line how to add read more text... please do guide
ReadMoreTextView is a good option for this purpose, with a few lines of code you can achieve this behavior.
#IBOutlet weak var aboutMessageTextView: ReadMoreTextView!
aboutMessageTextView.text = "your text"
let readMoreTextAttributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.foregroundColor: UIColor.systemBlue,
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14)
]
aboutMessageTextView.attributedReadMoreText = NSAttributedString(string: " ... Read more", attributes: readMoreTextAttributes)
aboutMessageTextView.maximumNumberOfLines = 3
aboutMessageTextView.shouldTrim = true
#objc func buttonRoundPlayer(){
view?.addSubview(buttonRound)
buttonRound.setTitle("Jump", for: .normal)
buttonRound.addTarget(self, action: #selector(roundhandle), for: .touchUpInside)
buttonRound.backgroundColor = .red
buttonRound.layer.cornerRadius = 5
buttonRound.layer.borderWidth = 1
buttonRound.layer.borderColor = UIColor.white.cgColor
buttonRound.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor),buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor),buttonRound.widthAnchor.constraint(equalToConstant: 100),buttonRound.heightAnchor.constraint(equalToConstant:50)])
}
I recently managed to get help in understanding the layout for the button and make it work but I don't know how to adjust the constraint to move the button away from the edge of the bottom side of the screen.
Thank you in advance for helping.
Not sure what do you mean by edge of bottom side, if you are talking about safe area layout guide, then you can use
NSLayoutConstraint.activate([buttonRound.bottomAnchor.constraint(equalTo:view!.safeAreaLayoutGuide.bottomAnchor),
buttonRound.widthAnchor.constraint(equalToConstant: 100),
buttonRound.heightAnchor.constraint(equalToConstant:50)])
Couple of issues in your code,
You have applied same constraint twice, which makes no logical sense to me
buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor),
buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor)
You force-unwrap view using view! am not really sure if its the ViewController's view or not, if it is ViewController's view, you need not force unwrap it as its a implicit optional in nature, so you should be able to write view.safeAreaLayoutGuide instead.
Through out the code you access view as if its optional, with statements like view?.addSubview(buttonRound), view!.bottomAnchor because am not really sure which view it is and if you are so sure its optional I would suggest using safe unwrap with if let, guard let instead of !
if let view = view {
view.addSubview(buttonRound)
buttonRound.setTitle("Jump", for: .normal)
buttonRound.addTarget(self, action: #selector(roundhandle), for: .touchUpInside)
buttonRound.backgroundColor = .red
buttonRound.layer.cornerRadius = 5
buttonRound.layer.borderWidth = 1
buttonRound.layer.borderColor = UIColor.white.cgColor
buttonRound.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([buttonRound.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor),
buttonRound.widthAnchor.constraint(equalToConstant: 100),
buttonRound.heightAnchor.constraint(equalToConstant:50)])
}
EDIT: As commented by OP below, he is seeing the error
"SafeAreLayoutGude" is only available in iOS 11.0 or newer
OP must be using a deployment target less than iOS 11 and because OP hasn't responded to my question in comment I am updating the answer to support below iOS 11.0
if let view = view {
view.addSubview(buttonRound)
buttonRound.setTitle("Jump", for: .normal)
buttonRound.addTarget(self, action: #selector(roundhandle), for: .touchUpInside)
buttonRound.backgroundColor = .red
buttonRound.layer.cornerRadius = 5
buttonRound.layer.borderWidth = 1
buttonRound.layer.borderColor = UIColor.white.cgColor
buttonRound.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([buttonRound.widthAnchor.constraint(equalToConstant: 100),
buttonRound.heightAnchor.constraint(equalToConstant:50)])
if #available(iOS 11.0, *) {
buttonRound.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
else {
buttonRound.bottomAnchor.constraint(equalTo:view.bottomAnchor).isActive = true
}
}
Not really sure what kind of app your are building/maintaining, iOS 11 seems way old to me, check if you really even need to support such old iOS version or not, change your iOS deployment target value in your project setting to avoid multiple compatibly issues like this.
open var buttonInit: ((_ index: Int) -> UIButton?)?
...
if let button: UIButton = self.buttonInit?(i) {
finButton = button
}else {
let button = UIButton(type: .custom)
button.setTitleColor(button.tintColor, for: [])
button.layer.borderColor = button.tintColor.cgColor
button.layer.borderWidth = 1
button.layer.cornerRadius = buttonHeight/2
finButton = button
}
I don't find any function description about buttonInit in AZDialogViewController. Does it mean button: UIButton = self.buttonInit?(i) will always be nil and finButton = button will not be executed?
The latter part of the code you quoted is in the setUpButton method:
fileprivate func setupButton(index i:Int) -> UIButton{
if buttonHeight == 0 {buttonHeight = CGFloat(Int(deviceHeight * 0.07))}
let finButton: UIButton
if let button: UIButton = self.buttonInit?(i) {
finButton = button
}else {
let button = UIButton(type: .custom)
button.setTitleColor(button.tintColor, for: [])
button.layer.borderColor = button.tintColor.cgColor
button.layer.borderWidth = 1
button.layer.cornerRadius = buttonHeight/2
finButton = button
}
This method is called here:
open func addAction(_ action: AZDialogAction){
actions.append(action)
if buttonsStackView != nil{
let button = setupButton(index: actions.count-1)
self.buttonsStackView.addArrangedSubview(button)
//button.frame = buttonsStackView.bounds
button.center = CGPoint(x: buttonsStackView.bounds.midX,y: buttonsStackView.bounds.maxY)
animateStackView()
}
}
From this we can see that buttonInit seems to be used to let the user of the library specify what kind of button they want as the action buttons. Another piece of evidence is that buttonInit is declared open, so it is likely that it is the client code who should set this, not the AZDialogViewController.
Plus, the README file showed this usage:
Use custom UIButton sub-class:
dialog.buttonInit = { index in
//set a custom button only for the first index
return index == 0 ? HighlightableButton() : nil
}
So to answer your question, the if branch will be executed if you set buttonInit.
#Huwell,
the documentation in the repository states to initialize the button in the following manner:
dialog.buttonInit = { index in
//set a custom button only for the first index
return index == 0 ? HighlightableButton() : nil
}
The button should be part of your DialogViewController.
My app crashes and throws this error
[UITouchesEvent rightView]: unrecognized selector sent to instance 0x13d5092e0
2016-08-04 17:07:15.569 [3809:1375151]
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITouchesEvent rightView]: unrecognized selector sent to instance 0x13d5092e0'
*** First throw call stack:
(0x180d72db0 0x1803d7f80 0x180d79c4c 0x180d76bec 0x180c74c5c 0x1000e681c 0x1000e6a60 0x185f08be8 0x185f08b64 0x185ef0870 0x185f11360 0x185f07ed8 0x185f00c20 0x185ed104c 0x185ecf628 0x180d2909c 0x180d28b30 0x180d26830 0x180c50c50 0x182538088 0x185f3a088 0x1000f5c88 0x1807ee8b8)
libc++abi.dylib: terminating with uncaught exception of type NSException
I'm trying to make a custom class for hide and show password so that I can use it in any UITextField in any UIViewController.
class HideShowIcon:NSObject {
var showPasswordImage = UIImage(named: "ic_show_password") as UIImage?
var hidePasswordImage = UIImage(named: "ic_hide_password") as UIImage?
func hideShowPasswordButton(hideText:UITextField) {
var hideShowSize: CGSize = "12345".sizeWithAttributes([NSFontAttributeName:UIFont.systemFontOfSize(14.0)])
var hideShow: UIButton = UIButton(type: UIButtonType.System)
hideShow.frame = CGRect(x: 0, y: 0, width: hideShowSize.width, height: hideText.frame.size.height)
hideShow.setImage(hidePasswordImage, forState: UIControlState.Normal)
hideText.rightView = hideShow
hideText.rightViewMode = UITextFieldViewMode.Always
hideShow.addTarget(self, action: #selector(HideShowIcon.hideShowPasswordTextField(_:hideText:)), forControlEvents: UIControlEvents.AllTouchEvents)
}
func hideShowPasswordTextField(sender: AnyObject,hideText:UITextField) {
var hideShow: UIButton = (hideText.rightView as? UIButton)!
if !hideText.secureTextEntry {
hideText.secureTextEntry = true
hideShow.setImage(hidePasswordImage, forState: UIControlState.Normal)
} else {
hideText.secureTextEntry = false
hideShow.setImage(showPasswordImage, forState: UIControlState.Normal)
}
hideText.becomeFirstResponder()
}
}
You can not use selector with many parameters hideShowPasswordTextField(_:hideText:) for UIButton target. You can only use selector with one (or zero) parameter, in which UIButton will put itself: hideShowPasswordTextField(_:)
func hideShowPasswordTextField(sender: UIButton) {
//...
}
To use hideText in this function, you may declare it as property of your class:
var hideText: UITextField!
and assign value to it in class initialization step
I created a UIBarButtonItem programmatically and the text is underlined. Is there a way to remove the underline?
let editButton = UIButton.init(type: .Custom)
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.title = "General Information"
editButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
editButton.addTarget(self, action: #selector(editButtonPressed(_:)), forControlEvents: .TouchUpInside)
editButton.frame.size = CGSize(width: 60, height: 30)
editButton.titleLabel?.adjustsFontSizeToFitWidth = true
let barButtonItem = UIBarButtonItem.init(customView: editButton)
self.tabBarController?.navigationItem.setRightBarButtonItem(barButtonItem, animated: true)
updateEditButtonTitle()
self.navigationController!.navigationItem.backBarButtonItem?.tintColor = UIColor.blackColor()
}
here is an image of the result I get, with the underline.
here is the function where I set the button's text. when it is pressed, it becomes a save button.
func updateEditButtonTitle() {
if let button = self.tabBarController?.navigationItem.rightBarButtonItem?.customView as? UIButton {
var title = ""
editButton.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
editButton.layer.cornerRadius = 7.0
if isInEditMode {
title = "Save"
editButton.setTitleColor(UIColor.redColor(), forState: .Normal)
editButton.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.5)
editButton.layer.cornerRadius = 7.0
editButton.frame.size = CGSize(width: 60, height: 30)
} else {
editButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
title = "Edit"
}
button.setTitle(title, forState: .Normal)
}
}
Try this code ..
var attrStr: NSMutableAttributedString = yourBtnHere.attributedTitleForState(.Normal).mutableCopy()
//or whatever the state you want
attrStr.enumerateAttributesInRange(NSMakeRange(0, attrStr.characters.count), options: .LongestEffectiveRangeNotRequired, usingBlock: {(attributes: [NSObject : AnyObject], range: NSRange, stop: Bool) -> Void in
var mutableAttributes: [NSObject : AnyObject] = [NSObject : AnyObject](dictionary: attributes)
mutableAttributes.removeObjectForKey(.AttributeName)
attrStr.setAttributes(mutableAttributes, range: range)
})
With the inspector/IB: Select your UIButton.
Show the Attributes Inspector.
The Text settings should be in Attributed. Select the text, click on the fond item remove the Underlining setting it at none.
enter image description here
But..
Let me get this straight. Apple added an accessibility feature that lets users mark buttons with underlines if they want to.
You want a way to defeat this feature, specifically designed to help people with handicaps use their devices, when the feature is something that the user has to ask for.
Why?
It is very likely not possible using standard buttons. If you did figure out a way to do it, Apple would likely reject your app because it defeats a system function meant to help the disabled.
So the answer is: Don't do that.