How to show image when textfield is empty only? - ios

i have 4 textfields, a button and an image, what i'm trying to achieve is that when the button is pressed it should warn the user there are empty textfields and show the image pointing to the empty textfield(s), but make the image disappear when the user put text into the empty textfield. Thank you
here is my func
func checkFields(){
let userEmail = user_EmailTxtField.text!
let userPassword = user_PassTxtField.text!
let passwordConfirm = pass_ConfirmTxtField.text!
let userPhone = user_PhoneTxtField.text!
//Set backArrow image to show input error to password
let imageName = "backArrow.png"
let image = UIImage(named: imageName)
let passImageView1 = UIImageView(image: image!)
passImageView1.frame = CGRect(x: 319, y: 331, width: 49, height: 49)
view.addSubview(passImageView1)
//Show Arrow image to password confirm error
let passConfirmImageView1 = UIImageView(image: image!)
passConfirmImageView1.frame = CGRect(x: 319, y: 394, width: 49, height: 49)
view.addSubview(passConfirmImageView1)
//Show arrow Image to email error
let emailImageView1 = UIImageView(image: image!)
emailImageView1.frame = CGRect(x: 319, y: 270, width: 49, height: 49)
view.addSubview(emailImageView1)
//Set image to phonetxt field error
let phoneImageView1 = UIImageView(image: image!)
phoneImageView1.frame = CGRect(x: 319, y: 209, width: 49, height: 49)
view.addSubview(phoneImageView1)
if userPhone.isEmpty {
phoneImageView1.isHidden = false
} else {
phoneImageView1.isHidden = true
}
if userEmail.isEmpty {
emailImageView1.isHidden = false
}
if userPassword.isEmpty {
passImageView1.isHidden = false
}
if passwordConfirm.isEmpty {
passConfirmImageView1.isHidden = false
}
}

You can call a function where you handle your check and then hide your image if the text isn't empty like this:
1 Add a target to your textFields at the place where you create them for the event .editingChanged:
user_EmailTxtField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
user_PhoneTxtField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
pass_ConfirmTxtField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
pass_ConfirmTxtField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
2 Setup the method you use to check if the textfields getting edited:
func textFieldDidChange() {
emailImageView1.isHidden = user_EmailTxtField.hasText
phoneImageView1.isHidden = user_PhoneTxtField.hasText
passImageView1.isHidden = pass_ConfirmTxtField.hasText
passConfirmImageView1.isHidden = pass_ConfirmTxtField.hasText
}
So if you apply this example to all your text fields you don't need the checks in checkFields() and you can rename your the method to setupTextFields() for example to use it only as creation of the text fields
Example to use your image views in all methods over the class, but be sure to initialize in viewDidLoad() for example to avoid found nil errors while unwrapping an optional value
class YourClass: UIViewController {
// ImageView Reference
var emailImageView1: UIImageView!
// then your checkFields method
func checkFields() {
// code before
emailImageView1 = UIImageView(image: image!)
// code after
}
}

you should separate the creation of the image (addSubview) and the check
put the creation to viewDidLoad
and later check the fields and hide it or show it.
just now you create each time a new image which is placed over the previous created images (you can check this if you switch to a wireframe 3d debug view)

Instead of checking if userPhone.isEmpty, you should try:
if user_EmailTxtField.text == nil {
phoneImageView1.isHidden = false
}
You could even do:
if user_EmailTxtField.text == nil || user_EmailTxtField.text == "" {
phoneImageView1.isHidden = false
}

Related

CGRect function is not working while placing image in textfield

I am trying to set image inside the textfield , and for that i am creating an image view in code but when i am trying to adjust its width and height via CGRect(x:int, y:int, width:int, height:int) , its not being applied and the image size is still original. I ve seen so many tutorials for putting image in text field and all of them are using CGRect and its working for them, as size of image gets what they apply in CGRect, but not for me. Below is the code i m trying to use. Image is also attached. Textfield style is rounded (Default) and icon size is 50px.
UIViewController
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var email: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
update()
// Do any additional setup after loading the view.
}
func update() {
email.leftViewMode = .always
let imageview = UIImageView()
let image = UIImage(named: "icon")
imageview.image = image
imageview.frame = CGRect(x: 15, y: 0, width: 50 , height: 50)
email.leftView = imageview
}
}
Also, i ve tried to change 'Render as' to 'template' in image assets but its still not working.
Hey I’ve tried to do it programmatically and it works for me. Quickly drafted it on iPad playgrounds. Try this:
class Test: UIViewController {
let lable = UITextField()
let image = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
lable.frame = CGRect(x: 200, y: 200, width: 300 , height: 50)
lable.backgroundColor = .black
update()
self.view.addSubview(lable)
}
func update() {
lable.leftViewMode = .always
let imageview = UIImageView()
let image = UIImage(systemName: "icloud")
imageview.image = image
imageview.frame = CGRect(x: 15, y: 0, width: 50 , height: 50)
lable.leftView = imageview
self.view.addSubview(imageview)
}
}

Assign tags for dynamic UIButtons

I found this example of a dynamic view of UIButtons at: http://helpmecodeswift.com/advanced-functions/generating-uibuttons-loop
I inserted this code into my app but unfortunately I can't find a way to set a tag for each buttons.
My target is to know which button is tapped, count the amount of clicks for each button and save this information into my DB.
override func viewDidLoad() {
super.viewDidLoad()
var arrayOfVillains = ["santa", "bugs", "superman", "batman"]
var buttonY: CGFloat = 20
for villain in arrayOfVillains {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGrayColor()
villainButton.setTitle("Button for Villain: \(villain)", forState: UIControlState.Normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self, action: "villainButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
}
func villainButtonPressed(sender:UIButton!) {
if sender.titleLabel?.text != nil {
println("You have chosen Villain: \(sender.titleLabel?.text)")
} else {
println("Nowhere to go :/")
}
}
}
So how it is possible to set and get the tag for/from each button in code (in this example)?
Thank you in advance!
You can use enumerated array to access indexes of the current item in iteration and use that as a tag:
override func viewDidLoad() {
super.viewDidLoad()
var arrayOfVillains = ["santa", "bugs", "superman", "batman"]
var buttonY: CGFloat = 20
for (index, villain) in arrayOfVillains.enumerated() {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
// set the tag to current index
villainButton.tag = index
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGrayColor()
villainButton.setTitle("Button for Villain: \(villain)", forState: UIControlState.Normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self, action: "villainButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
}
}
#objc func villainButtonPressed(sender:UIButton!) {
// tag of pressed button
print(">>> you pressed button with tag: \(sender.tag)")
if sender.titleLabel?.text != nil {
println("You have chosen Villain: \(sender.titleLabel?.text)")
} else {
println("Nowhere to go :/")
}
}
You should use an integer-based for loop for this.
for i in 0 ..< arrayOfVillains.count {
let villain = arrayOfVillains[i]
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
villainButton.tag = i
}
You can do as follows,
var buttonTag = 1
for villain in arrayOfVillains {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
villainButton.tag = buttonTag
buttonTag += 1
}

UITextField RightView image goes out of bounds

SO I have a textfield which is basically JVFloatLabeledTextField for floating texts and works upon checking if the username is available. If the webservice returns a response object that username already exists the textfields rightview sets a red alert image whereas if it returns that the username is available then the rightview imageview is set to something green.. Well the image is being set a bit out of bounds. I have tried everything.. Attached herewith is the snapshot, and here is the code:
usernameTextField.rightViewMode = UITextFieldViewMode.always
let imageView = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
var imageName:String = ""
if jsonReturned["errorCode"] == "Success" {
imageName = "isAcceptedIcon"
} else {
imageName = "isRejectedIcon"
}
let image = UIImage(named: imageName)
imageView.image = image
usernameTextField.rightView = imageView
Any help is greatly appreciated. I want to shift the image to a bit left. Thanks in advance.
SO I kind of solved it on my own. Its kind of very simple infact. Instead of appointing to the rightView, the imageView.. I had to set rightView's frame and then addSubview(imageView) to it. Here's the code and the new attached picture:
userEmailTextField.rightViewMode = UITextFieldViewMode.always
let imageView = UIImageView.init(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
usernameTextField.rightView?.frame = AppManager.shared.CGRectMake(0, 0, 25, 20)
var imageName:String = ""
if jsonReturned["errorCode"] == "Success" {
imageName = "isAcceptedIcon"
} else {
imageName = "isRejectedIcon"
}
let image = UIImage(named: imageName)
imageView.image = image
imageView.contentMode = .scaleAspectFit
usernameTextField.rightView?.addSubview(imageView)
So yeah that was a tremendous fix! Hope this helps someone else too :)

Detail Disclosure loading on top of the previous detail disclosure

I have a map view with annotations and every annotation has a corresponding date with day, month, and time.
I'm pushing the day to the new view controller then using a switch to see what day of the month it falls on and then displaying the corresponding calendar icon. I can't put the func anywhere other than viewDidAppear which cause a brief lag and two, prevents me from using
for view in self.view.subviews {
view.removeFromSuperview()
}
So two questions:
how can I call the dayCalendar function before viewDidAppear (anywhere else I've tried to put the code, it returns a nil)
how do I prevent my detailDisclosures from appearing on top of one another?
This is the code responsible for showing the image:
override func viewDidAppear(animated: Bool) {
dayCalendar()
}
func dayCalendar() {
switch day {
case 1:
let calendarDay = "Calendar 1-50.png"
let calendarDayImage = UIImage(named: calendarDay)
let calendarDayImageView = UIImageView(image: calendarDayImage!)
calendarDayImageView.frame = CGRect(x: 25 , y: 350, width: 50, height: 50)
self.view.addSubview(calendarDayImageView)
case 8:
let calendarDay = "Calendar 8-50.png"
let calendarDayImage = UIImage(named: calendarDay)
let calendarDayImageView = UIImageView(image: calendarDayImage!)
calendarDayImageView.frame = CGRect(x: 25 , y: 350, width: 50, height: 50)
self.view.addSubview(calendarDayImageView)
case 11:
let calendarDay = "Calendar 11-50.png"
let calendarDayImage = UIImage(named: calendarDay)
let calendarDayImageView = UIImageView(image: calendarDayImage!)
calendarDayImageView.frame = CGRect(x: 25 , y: 350, width: 50, height: 50)
self.view.addSubview(calendarDayImageView)
case 12:
blahh blahh blahh all the way down
case 31:
let calendarDay = "Calendar 30-50.png"
let calendarDayImage = UIImage(named: calendarDay)
let calendarDayImageView = UIImageView(image: calendarDayImage!)
calendarDayImageView.frame = CGRect(x: 25 , y: 350, width: 50, height: 50)
self.view.addSubview(calendarDayImageView)
default:
println("Default")
break
}
}
First off: why are you actually switching? As far as I can tell the code can be reduced to
func dayCalendar() {
if day < 1 || day > 31 {
return
}
let calendarDay = "Calendar \(day)-50.png"
let calendarDayImage = UIImage(named: calendarDay)
let calendarDayImageView = UIImageView(image: calendarDayImage!)
calendarDayImageView.frame = CGRect(x: 25 , y: 350, width: 50, height: 50)
self.view.addSubview(calendarDayImageView)
}
You might want to move the call to viewWillAppear.
To fix the overlaying of the detail closures you have two options:
remove the added calendarDayImageView every time you display a new day.
or (much better)
reuse the already added image view if it is already present (might want to create a lazy variable) and just change the image it is displaying.
The later one you can achieve in the following way:
// add this variable to your class
lazy var calendarDayImageView: UIImageView = {
[unowned self] in
let imageV = UIImageView(frame: CGRect(x: 25 , y: 350, width: 50, height: 50))
self.view.addSubview(imageV)
return imageV
}()
// change the dayCalender to make use of the newly added variable
func dayCalendar() {
if day < 1 || day > 31 {
return
}
let calendarDay = "Calendar \(day)-50.png"
let calendarDayImage = UIImage(named: calendarDay)
calendarDayImageView.image = calendarDayImage
}
Alternatively you can just move the initialization of the view inside viewDidLoad and have dayCalender again only set the actual image - but i like lazy vars ;)

ViewController won't reload properly on first Simulator launch

I have a weird issue that I just found out when I re-installed and launched my project first time on Simulator
My main ViewController has a collection view that will show a list of recipes. After a recipe is added and navigated back to this screen, the list will reflect the update.
There is also a ScrollView that appears when recipe.count > 0 with subview containing buttons (to filter list by category). The scrollview reflect the update on the recipes but it won't work on the very first launch in Simulator.
I've tried reloading collectionview, fetching recipe data on viewDidAppear, viewWillAppear but no luck with the first-time launch.
How can I make sure the first app launch experience is the same with the subsequent launches? Is there any known issue with first-time launch on Simulator that I should know about?
Here is the code that creates buttons and add to ScrollView.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
fetchRecipe()
collection.reloadData()
if recipes.count == 0 {
categoryScrollView.hidden = true
categoryScrollViewHeight.constant = 0
} else {
populateCategoryScrollView()
}
}
func populateCategoryScrollView() {
//Create category sort buttons based on fetched category.name and add to scrollview
if recipes.count > 0 {
var categories: [String] = []
for recipe in recipes {
if let value = recipe.category {
let category = value as! RecipeCategory
categories.append(category.name!)
}
}
var distinctCategories = Array(Set(categories))
var widthStack = 0
if distinctCategories.count != 0 {
for subView in categoryScrollView.subviews {
subView.removeFromSuperview()
}
for i in 0..<distinctCategories.count {
//Pilot button creation to get width
let frame1 = CGRect(x: 0, y: 6, width: 80, height: 40 )
let button = UIButton(frame: frame1)
button.setTitle("\(distinctCategories[i])", forState: .Normal)
button.sizeToFit()
let buttonWidth = Int(button.frame.size.width)
var frame2: CGRect
if i == 0 {
frame2 = CGRect(x: 10, y: 6, width: buttonWidth+20, height: 30 )
} else {
frame2 = CGRect(x: 10 + widthStack, y: 6, width: buttonWidth+20, height: 30 )
}
widthStack += buttonWidth+32
let button1 = UIButton(frame: frame2)
let attributedTitle = NSAttributedString(string: "\(distinctCategories[i])".uppercaseString, attributes: [NSKernAttributeName: 1.0, NSForegroundColorAttributeName: UIColor.blackColor()])
button1.setAttributedTitle(attributedTitle, forState: .Normal)
button1.titleLabel!.font = UIFont(name: "HelveticaNeue", size: 13.0)
button1.layer.borderWidth = 2.0
button1.layer.borderColor = UIColor.blackColor().CGColor
button1.backgroundColor = UIColor.whiteColor()
button1.addTarget(self, action: "filterByCategory:", forControlEvents: UIControlEvents.TouchUpInside)
self.categoryScrollView.addSubview(button1)
}
}
}
}
The first time you enter the application, the recipes.count is 0, so you are hiding the scroll view by the constraint categoryScrollViewHeight.constant = 0. So next time you create a new recipe, the scroll view is still with a zero height. That's why you didn't see the scroll on first time launch.

Resources