Material TextField previous next button - ios

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
}
}
}
}

Related

largeTitleTextAttributes disappear after programmatic push - Swift

I'm pushing to a navigation controller and the large title I have set within the shootSummary VC text attributes change without warning -- they lose their original formatting. So I've tried putting them as I've done here after the push, but that hasn't worked either. Here's my code:
guard let shootSummaryVC = storyboard?.instantiateViewController(withIdentifier: "ShootPVC") as? ShootPVC else { return }
guard let indexPath = tableView.indexPathForSelectedRow else { return }
guard let shootID = shoots?[indexPath.row].id else { return }
shootSummaryVC.id = shootID
shootSummaryVC.initialPage = 3
DispatchQueue.main.async { [self] in
navigationController?.pushViewController(shootSummaryVC, animated: true)
navigationController?.hidesNavigationBarHairline = true
navigationController?.navigationBar.topItem?.backBarButtonItem =
UIBarButtonItem(title: "Track Payments", style: .plain, target: nil, action: nil)
let p = NSMutableParagraphStyle()
p.firstLineHeadIndent = 10
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.font: currentTheme.titleFontLarge, NSAttributedString.Key.foregroundColor: currentTheme.navigationBarTextColor, NSAttributedString.Key.paragraphStyle: p]
}
The largeTitleTextAttributes in my attempted solution above don't affect the title. I tried setting them within the VC being pushed to (shootSummaryVC) but that hasn't worked either. Any ideas?

Swift: Not Return to English Version after translate to Arabic

i want to localize my apps between English and Arabic version included RTL. but it not return to English Version with left to right after translate to Arabic, it just repeats to Arabic version when i click navigation item UIButton, also navigation item flag not show properly it is just repeating Arabic flag.
// here is my code
import UIKit
import Foundation
// homeCollectionViewController
class HomeCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout{
let navLanguageBtn = UIButton()
static var language = ""
override func viewDidLoad() {
super.viewDidLoad()
setupHomeNavBarBtn()
}
// NavigationBar
func setupHomeNavBarBtn() {
navLanguageBtn.frame = CGRect(x: 0, y: 0, width: CollectionViewSize.width / 15, height: CollectionViewSize.width / 15)
navLanguageBtn.contentEdgeInsets = UIEdgeInsetsMake(0, 0, CollectionViewSize.width / 60, 0)
navLanguageBtn.setImage(UIImage(named: "arab_flag")?.withRenderingMode(.alwaysOriginal), for: .normal)
navLanguageBtn.contentMode = .scaleAspectFit
navLanguageBtn.addTarget(self, action: #selector(navLanguageBtnClick), for: .touchUpInside)
let navLanguageBtnItem = UIBarButtonItem(customView: navLanguageBtn)
self.navigationItem.setRightBarButtonItems([ navLanguageBtnItem], animated: true)
}
// ButtonClick
public func navLanguageBtnClick(){
if (navLanguageBtn.isSelected == true)
{
print("language btn click true English flag")
navLanguageBtn.setImage(UIImage(named: "english_flag")?.withRenderingMode(.alwaysOriginal), for: UIControlState.normal)
UIView.appearance().semanticContentAttribute = .forceRightToLeft
navLanguageBtn.isSelected = false
let path = Bundle.main.path(forResource: "ar-SA", ofType: "lproj")
let bundal = Bundle.init(path: path!)! as Bundle
HomeCollectionViewController.language = "ar"
navigationItem.title = bundal.localizedString(forKey: "home", value: nil, table: nil)
SecondHomeCell.newProductTrans = bundal.localizedString(forKey: "newProduct", value: nil, table: nil)
SecondHomeCell.populerStoriesTrans = bundal.localizedString(forKey: "populerStories", value: nil, table: nil)
let navController: UINavigationController? = (UIApplication.shared.keyWindow?.rootViewController as? UINavigationController)
let layout = UICollectionViewFlowLayout()
let control = HomeCollectionViewController(collectionViewLayout: layout)
navController?.pushViewController(control, animated: true)
let AR_POST_PARAMETERS = ["language": HomeCollectionViewController.language]
self.secondHomeCell?.secondHomeCellDataLoad(POST_PARAMETERS: AR_POST_PARAMETERS as! Dictionary<String, String>)
}
else
{
print("language btn click true arabic flag")
navLanguageBtn.setImage(UIImage(named: "arab_flag")?.withRenderingMode(.alwaysOriginal), for: UIControlState.selected)
UIView.appearance().semanticContentAttribute = .forceLeftToRight
// UIView.appearance().transform = CGAffineTransform(scaleX: 1.0, y: -1.0)
navLanguageBtn.isSelected = true
// self.lblCountryName.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
let path = Bundle.main.path(forResource: "en", ofType: "lproj")
let bundal = Bundle.init(path: path!)! as Bundle
//home
HomeCollectionViewController.language = "en"
navigationItem.title = bundal.localizedString(forKey: "home", value: nil, table: nil)
SecondHomeCell.newProductTrans = bundal.localizedString(forKey: "newProduct", value: nil, table: nil)
SecondHomeCell.populerStoriesTrans = bundal.localizedString(forKey: "populerStories", value: nil, table: nil)
let navController: UINavigationController? = (UIApplication.shared.keyWindow?.rootViewController as? UINavigationController)
let layout = UICollectionViewFlowLayout()
let control = HomeCollectionViewController(collectionViewLayout: layout)
navController?.pushViewController(control, animated: true)
let AR_POST_PARAMETERS = ["language": HomeCollectionViewController.language]
self.secondHomeCell?.secondHomeCellDataLoad(POST_PARAMETERS: AR_POST_PARAMETERS as! Dictionary<String, String>)
}
}
}
For changing the language of application, from a button click within the appliaction, i suggest you to ask the user to relaunch the application, for the change to happen.
In my application, i am changing the language like this.
//On Button click:
if applicationLanguage() == "ar" {
setApplicationLanguage(languageCode: "en-US")
}
else if applicationLanguage() == "en" {
setApplicationLanguage(languageCode: "ar")
}
func applicationLanguage() -> String
{
let languages : NSArray = UserDefaults.standard.object(forKey: "AppleLanguages") as! NSArray
let selectedLanguage : String = languages[0] as! String
return selectedLanguage.components(separatedBy: "-").first!
}
func setApplicationLanguage(languageCode : String)
{
// Show Alert to restart the application. Present it in your view controller.
UserDefaults.standard.set([languageCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
The user should manually quit the application, for the change to happen.

How to capture UIEvents of UIButton in custom framework?

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")
}

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?

Increment tab bar badge w/ UIAlertAction swift?

#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var tabArray = self.tabBarController?.tabBar.items as NSArray!
var tabItem = tabArray.objectAtIndex(1) as! UITabBarItem
let badgeValue = "1"
if let x = badgeValue.toInt() {
tabItem.badgeValue = "\(x)"
}
}
I don't know why I can't just do += "(x)"
Error:
binary operator '+=' cannot be applied to operands of type 'String?' and 'String'
I want it to increment by 1 each time the user selects "Yes". Right now obviously it just stays at 1.
You can try to access the badgeValue and convert it to Integer as follow:
Swift 2
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
nextValue = Int(badgeValue)?.successor() {
tabBarController?.tabBar.items?[1].badgeValue = String(nextValue)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
Swift 3 or later
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
let value = Int(badgeValue) {
tabBarController?.tabBar.items?[1].badgeValue = String(value + 1)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
To delete the badge just assign nil to the badgeValue overriding viewDidAppear method:
override func viewDidAppear(animated: Bool) {
tabBarController?.tabBar.items?[1].badgeValue = nil
}
Works with Swift 2:
let tabController = UIApplication.sharedApplication().windows.first?.rootViewController as? UITabBarController
let tabArray = tabController!.tabBar.items as NSArray!
let alertTabItem = tabArray.objectAtIndex(2) as! UITabBarItem
if let badgeValue = (alertTabItem.badgeValue) {
let intValue = Int(badgeValue)
alertTabItem.badgeValue = (intValue! + 1).description
print(intValue)
} else {
alertTabItem.badgeValue = "1"
}

Resources