Passing data without using storyboard or identifiers swift 3 - ios

I have created a textField in my main viewcontroller and want to pass data to another VC. I have created all of my UI programmatically, with out storyboard.
I tried passing data inside of a action I added to a button by doing the following:
let destination = InsuranceInformationViewController()
destination.customerNameLabel = customerNameTextField.text
But this does not work for me. Any help is appreciated, thanks in advance.
UPDATE
` //CustomerInformationViewController
override func viewDidLoad() {
super.viewDidLoad()
view.addSubView(customernameTextField)
view.addSubView(continueButton)
view.backgroundColor = UIColor.white
}
let customerNameTextField: UITextField = {
let textField = UITextField()
textField.placeHolderText = "First, Last"
textField.borderStyle = UITextBorderStyle.RoundedRect
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
let continueButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor.blue
button.setTitle("Continue", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitleColor(.white, for: .normal)
button.addTarget(self, action:#selector(CustomerInformationViewController ().continueOn), for: .touchUpInside)
return button
}()
#objc func continueOn (){
let destination = InsuranceInformationViewController()
destination.customerNameLabel = customerNameTextField.text
self.navigationController?.pushViewController(InsuranceViewController(), animated: true)
}
//InsuranceViewController
override func viewDidLoad() {
super.viewDidLoad()
view.addSubView(customerNameLabel)
view.backgroundColor = UIColor.white
}
let customerNameLabel: UILabel = {
let label = UILabel()
label.text = "Name"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
`

When you define destination let destination = InsuranceInformationViewController(), you are creating a new instance of InsuranceInformationViewController.
However in doing this, when you are referring to that instance, anything you try to change will not appear to work because it is not the already-instantiated view controller that you see in your view.
Instead you should do something like this:
let destination = storyboard?.instantiateViewController(withIdentifier: "YOUR_STORYBOARD_ID") as! InsuranceInformationViewController
destination.customerNameLabel = customerNameTextField.text
Hope this works

Related

When I set Image inside a type of custom button (for normal), voice over mode is saying image name. How can I disable it for the button imageview?

I've created a custom button and set two images, one is for normal, and the other is for the selected mode. But the voice-over always says the normal image name text when the button is not selected. I've tried a lot but could not disable it.
When I disable the button imageView accessibility it is not working.
button.imageView?.isAccessibilityElement = false
When I disable the button accessibility, the voice-over is not working in accessibility mode.
button.isAccessibilityElement = false
If I remove the '.normal' mode image then it works, but normal mode image functionality is not considered/worked there. I'm surfing a lot. Help anyone and thanks in advance.
Code:
self.setImage(UIImage.init(named: imageName1), for: .normal)
self.setImage(UIImage.init(named: imageName1), for: .selected)
You can do it with a simple function, this is an example...
Declare your image and your button under controller class:
let newButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = .red
button.tintColor = .white
button.imageView?.contentMode = .scaleAspectFit
button.clipsToBounds = true
return button
}()
let image1 = UIImage(named: "magnifier") // image in my assets
let image2 = UIImage(named: "user") // image in my assets
in viewDidLoad addTarget to your button and call the control function, in my case:
handleCange()
newButton.addTarget(self, action: #selector(handleCange), for: .touchUpInside)
now set control variable and handleCange() func
var controlButtonState = false
#objc fileprivate func handleCange() {
if controlButtonState == true {
newButton.setImage(image1, for: .normal)
controlButtonState = false
} else {
newButton.setImage(image2, for: .normal)
controlButtonState = true
}
}
Basically, it is not possible indirect way. On the other hand we can use accessibilityLabel
I found an alternative solution. I think it is not a proper solution. Nonetheless, I am sharing this alternative solution. The question is open if anyone gets any proper solutions. Thanks!
import UIKit
struct RadioViewControllerConstant {
static let dayImage = "RadioButtonDontSelect"
static let dayImageSelected = "RadioButtonSelect"
}
class RadioViewController: UIViewController {
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
let image1 = UIImage(named: RadioViewControllerConstant.dayImageSelected)
let image2 = UIImage(named: RadioViewControllerConstant.dayImage)
var controlButtonState1 = false
var controlButtonState2 = false
override func viewDidLoad() {
super.viewDidLoad()
setVO()
}
func setVO() {
button1.accessibilityTraits = .none
button2.accessibilityTraits = .none
button1.isSelected = true
button2.isSelected = true
handleCange1()
handleCange2()
button1.addTarget(self, action: #selector(handleCange1), for: .touchUpInside)
button2.addTarget(self, action: #selector(handleCange2), for: .touchUpInside)
}
#objc fileprivate func handleCange1() {
if controlButtonState1 == true {
button1.imageView?.accessibilityLabel = "Radio button deselected"
button1.setImage(image2, for: .selected)
controlButtonState1 = false
} else {
button1.imageView?.accessibilityLabel = "Radio button selected"
button1.setImage(image1, for: .selected)
controlButtonState1 = true
}
}
#objc fileprivate func handleCange2() {
if controlButtonState2 == true {
button2.imageView?.accessibilityLabel = "Radio button deselected"
button2.setImage(image2, for: .selected)
controlButtonState2 = false
} else {
button2.imageView?.accessibilityLabel = "Radio button selected"
button2.setImage(image1, for: .selected)
controlButtonState2 = true
}
}
}

swift cannot add target to UIButton

so this question is super simple, but i checked that like a 100 times but it still won't work.
Basically, when user taps on tableView cell, it open another VC with different views, depending whether or not user is owner of post.
First condition, works just fine, adding target to button, while when second is being executed, nothing happens
lazy var buttonsView = DetailButtonsView() // those are almost the same
lazy var addvertView = AdvertiseView()
// inside of buttonsView()
lazy var skipButton: UIButton = {
let button = UIButton()
button.setTitle("Пожаловаться", for: .normal)
button.setTitleColor(.mainColor, for: .normal)
button.titleLabel?.font = .getPoppinsMediumFont(on: 15)
return button
}()
override init(frame: CGRect) {
super.init(frame: .zero)
setupView() //set up constraints
}
//inside of AdvertiseView()
lazy var blackButton:UIButton = {
var button = UIButton()
button.layer.cornerRadius = 8
button.backgroundColor = .black
return button
}()
override init(frame: CGRect) {
super.init(frame: .zero)
setupView() //set up constraints
}
//
func setUpBottom() -> Void {
if dataInfo!.user_id! == UserSettings.userModel.id
{
self.backView.addSubview(addvertView) //also works
addvertView.snp.makeConstraints //works
{
(make) in
make.left.equalToSuperview()
make.top.equalTo(userView.snp.bottom).offset(24)
make.height.equalTo(450)
make.bottom.lessThanOrEqualTo(-34)
}
addvertView.blackButton.addTarget(self, action: #selector(blackButtonMethod), for: .touchUpInside) // does not add target
}
else {
backView.addSubview(buttonsView) //works
buttonsView.snp.makeConstraints { (make) in
make.left.right.equalToSuperview()
make.top.equalTo(userView.snp.bottom).offset(24)
make.bottom.lessThanOrEqualTo(-34)
}
buttonsView.skipButton.addTarget(self, action: #selector(toComplain), for: .touchUpInside) //works
}
#objc func toComplain(){ //works
let vc = ComplaintTypeViewController()
vc.advertID = dataInfo!.id!
navigationController?.pushViewController(vc, animated: true)
}
#objc func blackButtonMethod(){ //does not work
print("hello")
parameters["action"] = "hot"
parameters["advert_id"] = String(describing: dataInfo!.id)
updateAdvert(parameters: parameters)
}
The target is probably added, but you cannot interact with it. That usually happens when constraints/frame is not set right. I see that the skip button uses:
button.setTitle("Пожаловаться", for: .normal)
which will infer autolayout width/height.
I don't see black blackButton's autolayout constraints or label set anywhere.

Keep track of which UITextField is currently in editing mode

In the following code I have a couple buttons showing as an inputAccessoryView when inputFieldOne is in editing mode, when you tap First Button, it inputs ONE inside inputFieldOne and when I tap Second Button it inputs TWO inside inputFieldOne. It works as expected but what I would like to be able to do is re-use these buttons in multiple UITextFields. In other words, if I have another UTTextField called inputFieldTwo, I would like to be able to also input the values from those buttons when they're tapped.
How can I keep track of what UITextField is currently in editing mode so I can append the values from the buttons?
#IBOutlet weak var inputFieldOne: UITextField!
#IBOutlet weak var inputFieldTwo: UITextField!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addButtonsToKeyboard()
}
func addButtonsToKeyboard(){
// First button
let button1 = UIButton()
button1.setTitle("First Button", for: UIControl.State())
button1.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton1 = UIBarButtonItem()
barButton1.customView = button1
// Second button
let button2 = UIButton()
button2.setTitle("Second Button", for: UIControl.State())
button2.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton2 = UIBarButtonItem()
barButton2.customView = button2
/// UIToolbar.
let toolBar = UIToolbar()
toolBar.tintColor = UIColor.blue
toolBar.barTintColor = UIColor.red
toolBar.items = [barButton1, barButton2]
toolBar.sizeToFit()
inputFieldOne.inputAccessoryView = toolBar
}
#objc func buttonKeyPress(_ sender: UIButton){
switch sender.currentTitle!{
case "First Button":
inputFieldOne.text = "ONE"
case "Second Button":
inputFieldOne.text = "TWO"
default: break
}
}
There are many ways to make it reusable as i have very limited time so i suggest you can do it with Extension
You can use it for you all textfield
So here is the code snippet:
extension UITextField
{
// you can pass here array of UIbarbutton also
func addButtonsToKeyboard(){
// First button
let button1 = UIButton()
button1.setTitle("First Button", for: UIControl.State())
button1.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton1 = UIBarButtonItem()
barButton1.customView = button1
// Second button
let button2 = UIButton()
button2.setTitle("Second Button", for: UIControl.State())
button2.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton2 = UIBarButtonItem()
barButton2.customView = button2
/// UIToolbar.
let toolBar = UIToolbar()
toolBar.tintColor = UIColor.blue
toolBar.barTintColor = UIColor.red
toolBar.items = [barButton1, barButton2]
toolBar.sizeToFit()
self.inputAccessoryView = toolBar
}
#objc func buttonKeyPress(_ sender: UIButton){
switch sender.currentTitle!{
case "First Button":
self.text = "ONE"
case "Second Button":
self.text = "TWO"
default: break
}
}
}
And with you textfield object you can add it with below code
txtSwift.addButtonsToKeyboard()
Hope it help you!!!

How can a UIButton listen to changes to other Buttons, a change to a UILabel's text, and a change to a UITextView all at the same time

My vc contains:
-1 name textView
-1 label // for flavors
-2 radio buttons // yes and no
-1 nextButton
What I want to do is keep the nextButton disabled until the textView is filled out, the label's text value is changed from its initial title of "Pick a Flavor" to whatever flavor they pick, and 1 of the radio buttons are selected.
I know using a textView's textViewDidEndEditing() I can listen to changes on it after the user finishes editing disable or enable the nextButton.
func textViewDidEndEditing(_ textView: UITextView) {
handleTextInputChanged()
}
#objc func handleTextInputChanged() {
let isFormValid = nameTextView.text?.count ?? 0 > 0
if isFormValid {
nextButton.isEnabled = true
nextButton.backgroundColor = .red
} else {
nextButton.isEnabled = false
nextButton.backgroundColor = .lightgray
}
}
How would I additionally disable or enable the nextButton based on wether or not one of the radio buttons were selected and the label's text is changed in addition to checking the nameTextView has text inside of it?
FYI the label's text is initially set with "Pick a Flavor". I have a gesture recognizer hooked up to it and when its tapped a new vc with a tableView is presented. The user picks a flavor, a protocol sends it back to this vc and the label's text will change to whatever flavor was selected (eg the label's title would say "Butter Pecan" if chosen). The nextButton should be disabled as long as the label's title is still set to "Pick a Flavor".
code:
let flavorLabel: UILabel = {
let label = UILabel()
label.text = "Pick a Flavor"
label.isUserInteractionEnabled = true
return label
}()
let nameTextView: UITextView = {
let textView = UITextView()
return textView
}()
let noButton: DLRadioButton = {
let button = DLRadioButton(type: .custom)
button.setTitle("No", for: .normal)
button.setTitleColor(UIColor.lightGray, for: .normal)
button.addTarget(self, action: #selector(noButtonPressed), for: .touchUpInside)
return button
}()
let yesButton: DLRadioButton = {
let button = DLRadioButton(type: .custom)
button.setTitle("Yes", for: .normal)
button.setTitleColor(UIColor.lightGray, for: .normal)
button.addTarget(self, action: #selector(yesButtonPressed), for: .touchUpInside)
return button
}()
let nextButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Next", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.isEnabled = false
button.backgroundColor = .lightGray
button.addTarget(self, action: #selector(nextButtonTapped), for: .touchUpInside)
return button
}()
var choice: Bool?
override func viewDidLoad() {
super.viewDidLoad()
flavorVC.delegate = self
}
func textViewDidEndEditing(_ textView: UITextView) {
handleTextInputChanged()
}
#objc func handleTextInputChanged() {
let isFormValid = nameTextView.text?.count ?? 0 > 0
if isFormValid {
nextButton.isEnabled = true
nextButton.backgroundColor = .red
} else {
nextButton.isEnabled = false
nextButton.backgroundColor = .lightgray
}
}
#objc fileprivate func noButtonPressed() {
choice = false
}
#objc fileprivate func yesButtonPressed() {
choice = true
}
// delegate method from FlavorController
func selectedFlavor(flavor: String) {
flavorLabel.text = flavor // eg. "Butter Pecan"
}
You need to create a function that check all like this
func checkAll() {
nextButto.isEnabled = flavorLabel.text != "Pick a Flavor" &&
nameTextField.text != "" &&
(noButton.someProerty != || yesButton.someProerty != )
}
and call it from textfield and button targets plus
var ob:NSKeyValueObservation?
ob = flavorLabel.observe(\.text,options:[.new], changeHandler: { [unowned self] _, change in
self.checkAll()
}
I left the radio checks because both of them are custom , so you should know what to check , btw you can set tag of selected to 1 inside the target method and check according to it or some other logic you want

unable to build UI if the function is called from object of a class

I have a function to create the UIButton. I am calling that method in the same class using the object of its class.
If I call that function using its object, no UI is created. if I call that method as just self.createbutton() button is created.
class myClass: UIViewController {
let mainview = UIStackView()
func createbutton() {
let loadpageview = UIStackView()
loadpageview.axis = UILayoutConstraintAxis.vertical
loadpageview.distribution = UIStackViewDistribution.equalSpacing
loadpageview.alignment = UIStackViewAlignment.center
loadpageview.tag = 30
loadpageview.spacing = 16.0
let buttn = UIButton()
buttn.backgroundColor = .gray
buttn.setTitle("testttt", for: .normal)
buttn.frame.size.height = 30
buttn.frame.size.width = 40
buttn.addTarget(self, action: #selector(loginaction), for: .touchUpInside)
loadpageview.addArrangedSubview(buttn)
mainview.addArrangedSubview(loadpageview)
}
func mainviewlet() {
mainview.axis = UILayoutConstraintAxis.vertical
mainview.distribution = UIStackViewDistribution.equalSpacing
mainview.alignment = UIStackViewAlignment.center
mainview.spacing = 16.0
mainview.tag = 50
mainview.translatesAutoresizingMaskIntoConstraints = false;
self.view.addSubview(mainview)
}
}
If I create the object of the above class and call createbutton() , it wont work
override func viewDidLoad() {
super.viewDidLoad()
self.mainviewlet()
let pl = myClass()
pl.createbutton()
}
It works, if I call the method as follows :
override func viewDidLoad() {
super.viewDidLoad()
self.mainviewlet()
self.createbutton()
}
What's wrong here ? How can I call the method using its object. Further I am calling it from another class. Hence I need this. Thank you for any help!
In first example You are creating another instance of myClass() and a method in that reference will be called. But you want your Button created in current instance of the Class.
override func viewDidLoad() {
super.viewDidLoad()
self.mainviewlet()
let pl = myClass()
pl.createbutton()
}
But in working example you are referring current instance of the Class. So the UIButton it is creating is visible.
override func viewDidLoad() {
super.viewDidLoad()
self.mainviewlet()
self.createbutton()
}
Its Simple OOPS
Happy Coding
To make it work with instance of another class create your view in separate class say MyView. Then create a function which will return your
required view. Then call this function from your view controller on the object of that class , you will get your view, in your case it's UIStackView, finally add this as subview of the main view of the view controller.
Class MyView:NSObject{
func createbuttonWith(stackView:UIStackView) {
let loadpageview = UIStackView()
loadpageview.axis = UILayoutConstraintAxis.vertical
loadpageview.distribution = UIStackViewDistribution.equalSpacing
loadpageview.alignment = UIStackViewAlignment.center
loadpageview.tag = 30
loadpageview.spacing = 16.0
let buttn = UIButton()
buttn.backgroundColor = .gray
buttn.setTitle("testttt", for: .normal)
buttn.frame.size.height = 30
buttn.frame.size.width = 40
buttn.addTarget(self, action: #selector(loginaction), for: .touchUpInside)
loadpageview.addArrangedSubview(buttn)
stackView.addArrangedSubview(loadpageview)
}
func mainviewlet()->UIStackView {
let mainView = UIStackView()
mainview.axis = UILayoutConstraintAxis.vertical
mainview.distribution = UIStackViewDistribution.equalSpacing
mainview.alignment = UIStackViewAlignment.center
mainview.spacing = 16.0
mainview.tag = 50
mainview.translatesAutoresizingMaskIntoConstraints = false;
return mainView
}
}
Then in your view controller's viewDidLoad(),
let myView = MyView()
let mainViewLet = myView.mainviewlet()
self.view.addSubview(mainViewLet)
myView.createbuttonWith(mainViewLet)

Resources