How to capture UIEvents of UIButton in custom framework? - ios

I create my own framework and in that I need to provide a button and clicking on button I will do something predefined in framework.
Here is my code.
public class WebButton: NSObject {
public func enableWebButton(enable:Bool)
{
if(enable)
{
let appWindow = UIApplication.sharedApplication().keyWindow
let webBtn = UIButton(frame:CGRectMake((appWindow?.frame.size.width)! - 70,(appWindow?.frame.size.height)! - 70,50,50))
let frameworkBundle = NSBundle(forClass: self.classForCoder)
let img = UIImage(named: "btn_icon.png", inBundle: frameworkBundle, compatibleWithTraitCollection: nil)
webBtn.setImage(img, forState: .Normal)
webBtn.layer.cornerRadius = webBtn.frame.size.width / 2;
webBtn.layer.masksToBounds = true
webBtn.addTarget(self, action: "webButtonClick", forControlEvents: .TouchUpInside)
appWindow?.addSubview(webBtn)
print("btn created")
}
}
func webButtonClick()
{
print("btn Clicked")
}
}
In this code, I am getting button on my sample project, but clicking on button, nothing happens.
"btn created"
log is going to print, but
"btn Clicked"
is never going to print.
Please help me to solve this issue.
Thanks in advance.

Try using this code for creating your button and your webButtonClick function:
public func enableWebButton(enable:Bool)
{
if(enable)
{
let appWindow = UIApplication.sharedApplication().keyWindow
let webBtn = UIButton(frame:CGRectMake((appWindow?.frame.size.width)! - 70,(appWindow?.frame.size.height)! - 70,50,50))
let frameworkBundle = NSBundle(forClass: self.classForCoder)
let img = UIImage(named: "btn_icon.png", inBundle: frameworkBundle, compatibleWithTraitCollection: nil)
webBtn.setImage(img, forState: .Normal)
webBtn.layer.cornerRadius = webBtn.frame.size.width / 2;
webBtn.layer.masksToBounds = true
webBtn.addTarget(self, action: "webButtonClick:", forControlEvents: UIControlEvents.TouchUpInside)
appWindow?.addSubview(webBtn)
print("btn created")
}
}
func webButtonClick(sender:UIButton!)
{
print("btn Clicked")
}

Related

Primitive type parameters in Swift Selector function

I want to add dynamic number of buttons to my VC. So i am looping through my buttons array model and instantiating UIButtons. The problem is with adding target to these buttons. I want to pass in a string to the selector when adding a target, however Xcode compiler doesn't let me do that
Argument of '#selector' does not refer to an '#objc' method, property, or initializer
#objc func didTapOnButton(url: String) { }
let button = UIButton()
button.addTarget(self, action: #selector(didTapOnButton(url: "Random string which is different for every bbutton ")), for: .touchUpInside)
Is there any other solution other than using a custom UIButton
I don't think it is possible to do what you are attempting, you can try like this:
var buttons: [UIButton: String] = []
let button = UIButton()
let urlString = "Random string which is different for every button"
buttons[button] = urlString
button.addTarget(self, action: #selector(didTapOnButton), for: .touchUpInside
#objc func didTapOnButton(sender: UIButton) {
let urlString = self.buttons[sender]
// Do something with my URL
}
As I remember UIButton is hashable...
Another option would be to extend UIButton to hold the information you want:
extension UIButton {
private static var _urlStringComputedProperty = [String: String]()
var urlString String {
get {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
return Self._urlStringComputedProperty[tmpAddress]
}
set(newValue) {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
Self._urlStringComputedProperty[tmpAddress] = newValue
}
}
}
let button = UIButton()
button.urlString = "Random string which is different for every button"
button.addTarget(self, action: #selector(didTapOnButton), for: .touchUpInside
#objc func didTapOnButton(sender: UIButton) {
let urlString = sender.urlString
// Do something with my URL
}

How to delete cached SDWebImage from a button's imageView

So I have a UIButton whose imageView is set to an image using a download URL. For this purpose I use SDWebImage.
Problem is, when I press the delete button, I want the image to completely disappear but I guess it does not work because the image is still being retrieved from cache. How do I solve this?
class ViewController: UIViewController{
var profileButton: UIButton = {
let button = UIButton(type: .system)
return button
}()
var user: User?
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(profileButton)
profileButton.addTarget(self, action: #selector(handleDelete), for: .touchUpInside)
self.loadUserPhotos()
}
fileprivate func loadUserPhotos(){
let profileImageUrl = self.user?.profileImageUrl1
if let imageUrl = profileImageUrl, let url = URL(string: imageUrl){
SDWebImageManager.shared().loadImage(with: url, options: .continueInBackground, progress: nil) { (image, _, _, _, _, _) in
self.profileButton.setImage(image?.withRenderingMode(.alwaysOriginal), for: .normal)
}
}
}
#objc func handleDelete(){
self.user?.profileImageUrl1 = ""
self.profileButton.imageView?.image = nil
self.loadUserPhotos()
}
}
To remove the image from UIButton you need to mention the state as well.
self.profileButton.setImage(nil, for: .normal)
You can use :
SDImageCache.shared.removeImage(forKey: url?.description, withCompletion: nil)

Material TextField previous next button

I am trying to get the previous/next arrow button on top of the keyboard when ever a textField is selected.
I have tried the following
textField0.tag = 0 // textField0 : TextField
textField0.addPreviousNextRightOnKeyboardWithTarget(self, rightButtonTitle: "Submit", previousAction: #selector(previousTextField(sender:)), nextAction: #selector(nextTextField(sender:)), rightButtonAction: #selector(saveNewPlan), titleText: nil)
textField1.tag = 1
textField1.addPreviousNextRightOnKeyboardWithTarget(self, rightButtonTitle: "Submit", previousAction: #selector(previousTextField(sender:)), nextAction: #selector(nextTextField(sender:)), rightButtonAction: #selector(saveNewPlan), titleText: nil)
The previous/next action selector defined as such.
func previousTextField(sender: AnyObject){
// I actually get the sender as IQBarButtonItem (subclass of UIBarButtonItem) instead of UITextField here
if let previousField = textField.superview?.viewWithTag(textField.tag - 1) as? UITextField {
_ = previousField.becomeFirstResponder()
}
}
func nextTextField(sender: AnyObject){
if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {
_ = nextField.becomeFirstResponder()
}
}
It's throwing this error whenever I click on the button.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[IQKeyboardManagerSwift.IQBarButtonItem superview]: unrecognized selector sent to instance 0x7fc3775658e0'
Here's what the method do.
public func addPreviousNextRightOnKeyboardWithTarget( _ target : AnyObject?, rightButtonTitle : String, previousAction : Selector, nextAction : Selector, rightButtonAction : Selector, titleText : String?) {
//If can't set InputAccessoryView. Then return
if self.responds(to: #selector(setter: UITextField.inputAccessoryView)) {
// Creating a toolBar for phoneNumber keyboard
let toolbar = IQToolbar()
toolbar.doneTitle = rightButtonTitle
var items : [UIBarButtonItem] = []
let prev : IQBarButtonItem
let next : IQBarButtonItem
// Get the top level "bundle" which may actually be the framework
var bundle = Bundle(for: IQKeyboardManager.self)
if let resourcePath = bundle.path(forResource: "IQKeyboardManager", ofType: "bundle") {
if let resourcesBundle = Bundle(path: resourcePath) {
bundle = resourcesBundle
}
}
var imageLeftArrow : UIImage!
var imageRightArrow : UIImage!
if #available(iOS 10.0, *) {
imageLeftArrow = UIImage(named: "IQButtonBarArrowUp", in: bundle, compatibleWith: nil)
imageRightArrow = UIImage(named: "IQButtonBarArrowDown", in: bundle, compatibleWith: nil)
} else {
imageLeftArrow = UIImage(named: "IQButtonBarArrowLeft", in: bundle, compatibleWith: nil)
imageRightArrow = UIImage(named: "IQButtonBarArrowRight", in: bundle, compatibleWith: nil)
}
//Support for RTL languages like Arabic, Persia etc... (Bug ID: #448)
if #available(iOS 9.0, *) {
imageLeftArrow = imageLeftArrow?.imageFlippedForRightToLeftLayoutDirection()
imageRightArrow = imageRightArrow?.imageFlippedForRightToLeftLayoutDirection()
}
prev = IQBarButtonItem(image: imageLeftArrow, style: UIBarButtonItemStyle.plain, target: target, action: previousAction)
prev.accessibilityLabel = "Toolbar Previous Button"
next = IQBarButtonItem(image: imageRightArrow, style: UIBarButtonItemStyle.plain, target: target, action: nextAction)
next.accessibilityLabel = "Toolbar Next Button"
//Previous button
items.append(prev)
//Fixed space
let fixed = IQBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
if #available(iOS 10.0, *) {
fixed.width = 6
} else {
fixed.width = 20
}
items.append(fixed)
//Next button
items.append(next)
//Flexible space
items.append(UIView.flexibleBarButtonItem())
//Title button
let title = IQTitleBarButtonItem(title: shouldHidePlaceholderText == true ? nil : titleText)
items.append(title)
//Flexible space
items.append(UIView.flexibleBarButtonItem())
//Right button
let doneButton = IQBarButtonItem(title: rightButtonTitle, style: UIBarButtonItemStyle.done, target: target, action: rightButtonAction)
items.append(doneButton)
// Adding button to toolBar.
toolbar.items = items
toolbar.toolbarTitleInvocation = self.titleInvocation
// Setting toolbar to keyboard.
if let textField = self as? UITextField {
textField.inputAccessoryView = toolbar
switch textField.keyboardAppearance {
case UIKeyboardAppearance.dark:
toolbar.barStyle = UIBarStyle.black
default:
toolbar.barStyle = UIBarStyle.default
}
} else if let textView = self as? UITextView {
textView.inputAccessoryView = toolbar
switch textView.keyboardAppearance {
case UIKeyboardAppearance.dark:
toolbar.barStyle = UIBarStyle.black
default:
toolbar.barStyle = UIBarStyle.default
}
}
}
}

UIButton.addTarget with swift 3 and local function

I'm trying to generate multiple buttons programmatically. For the moment, here is what I've got :
for i in POIArray {
let newI = i.replacingOccurrences(of: "GPS30", with: "")
let button = UIButton(type: .custom)
button.setImage(UIImage(named: newI), for: .normal)
button.frame.size.height = 30
button.frame.size.width = 30
button.addTarget(self, action: #selector(buttonAction(texte:newI)), for: UIControlEvents.touchUpInside)
XIBMenu?.stackMenuIco.addArrangedSubview(button)
}
and my function :
func buttonAction(texte: String) {
print("Okay with \(texte)")
}
When I remove the parameter 'texte', it's working. The buttons are well added to the stack but I need that parameter to pass a variable. I get a buildtime error :
Argument of '#selector' does not refer to an '#objc' method, property, or initializer
Yes thank you XCode I know that it's not an objc method, because I'm coding in swift!
Anyone knows a way around ?
Here you need to use objc_setAssociatedObject
Add extension in project:-
extension UIButton {
private struct AssociatedKeys {
static var DescriptiveName = "KeyValue"
}
#IBInspectable var descriptiveName: String? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.DescriptiveName) as? String
}
set {
if let newValue = newValue {
objc_setAssociatedObject(
self,
&AssociatedKeys.DescriptiveName,
newValue as NSString?,
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN
)
}
}
}
}
How to use :-
//let newI = i.replacingOccurrences(of: "GPS30", with: "")
button?.descriptiveName = "stringData" //newI use here
How to get parameter :-
func buttonAction(sender: UIButton!) {
print(sender.descriptiveName)
}

How to pass extra arguments in selector?

I have this piece of code
class func catchWeightList(catchWeightButton : UIButton, productCatchWeightList:NSArray){
let window = UIApplication.sharedApplication().keyWindow
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
let catchWeightVC = CatchWeight.init(nibName: "CatchWeight", bundle: nil,dataSource: productCatchWeightList, catchWeightButton: catchWeightButton)
if catchWeightVC.view.superview == nil {
let y = catchWeightButton.frame.origin.y+catchWeightButton.frame.height+64
catchWeightVC.view.frame = CGRectMake(catchWeightButton.frame.origin.x, y ,catchWeightButton.frame.width, 90)
window?.addSubview(catchWeightVC.view)
window?.addGestureRecognizer(tap)
}
else{
catchWeightVC.view.removeFromSuperview()
window?.removeGestureRecognizer(tap)
}
}
class func handleTap(sender: UITapGestureRecognizer? = nil) {
// catchWeightVC?.view.removeFromSuperview()
let window = UIApplication.sharedApplication().keyWindow
window?.removeGestureRecognizer(sender!)
}
How to pass catchWeightVC in handleTap?

Resources