Hello, I am getting two errors for textFieldDidChange ( Swift) - swift

Can someone please help me out? I am getting these two errors
use of unresolved identifier
and
use of local variable textFieldDidChange before its declaration
Here is my code
override func viewDidLoad() {
super.viewDidLoad()
// Setting text field delegates
emailTextField.delegate = self
passwordTextField.delegate = self
// Disable login button until both textFields are not nil
textField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
}
func textFieldDidChange() {
if (emailTextField.text?.isEmpty)! || (passwordTextField.text?.isEmpty)! {
print("text is empty")
loginButton.isEnabled = false
loginButton.alpha = 0.33
} else {
loginButton.isEnabled = true
loginButton.alpha = 0.55
}
}
Edit
Question has been answered however I noticed the button would enable after I typed into the first textField. So I changed the && to || because I wanted the button to be disabled until both textFields weren't empty. Just for anyone who has this issue as well.

Your textFieldDidChange method should be outside the viewDidLoad and should be prefix-ed with #objc since it is a selector.
class YourClass: UIViewController {
// Your code
override func viewDidLoad() {
super.viewDidLoad()
// Setting text field delegates
emailTextField.delegate = self
passwordTextField.delegate = self
// Disable login button until both textFields are not nil
emailTextField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
passwordTextField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
}
#objc func textFieldDidChange() {
if (emailTextField.text?.isEmpty)! && (passwordTextField.text?.isEmpty)! {
print("text is empty")
loginButton.isEnabled = false
loginButton.alpha = 0.33
} else {
loginButton.isEnabled = true
loginButton.alpha = 0.55
}
}
}
And the target should be added to the respective text fields - emailTextField and passwordTextField.

You have missed to place "}" for viewDidLoad method
override func viewDidLoad() {
super.viewDidLoad()
// Setting text field delegates
emailTextField.delegate = self
passwordTextField.delegate = self
// Disable login button until both textFields are not nil
textField.addTarget(self, action: #selector(textFieldDidChange), for: UIControlEvents.editingChanged)
}
#objc func textFieldDidChange() {
if (emailTextField.text?.isEmpty)! && (passwordTextField.text?.isEmpty)! {
print("text is empty")
loginButton.isEnabled = false
loginButton.alpha = 0.33
} else {
loginButton.isEnabled = true
loginButton.alpha = 0.55
}
}

Related

UINavigationBar LargeTitle , searchbar didn't work

enter image description here
enter image description here
I want to make it like the picture below, but it comes out like the picture above.
Here is My Code.
lazy var button = UIDropDownButton().then {
$0.setAction().subscribe(onNext: {
switch $0 {
case .popularity: break
// 인기순 정렬 코드
case .suggestion: break
// 추천순 정렬 코드
case .lowestPrice: break
// 최저가순 정렬 코드
}
})
.disposed(by: disposeBag)
}
lazy var barButtonItem = UIBarButtonItem(customView: button)
override func viewDidLoad() {
super.viewDidLoad()
setNavigationBar()
}
override func viewWillAppear(_ animated: Bool) {
setNavigationBar()
}
private func setNavigationBar() {
setLargeTitleNavigationBar(title: "제품")
self.navigationItem.rightBarButtonItem = barButtonItem
let searchController = UISearchController(searchResultsController: nil)
self.navigationItem.searchController = searchController
}
setLargeTitleNavigationBar Method is here.
extension UIViewController {
func setLargeTitleNavigationBar(title: String) {
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.setBackButon()
self.navigationController?.navigationBar.backgroundColor = nil
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.setBackgroundImage(nil, for: UIBarMetrics.default)
self.navigationItem.title = title
}
I don't know how to solve this problem.
I like Snapkit, but I can read storyboard.
use this
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always

How to fix UIButton not responding to touch?

I am working an app with quizzes, have 4 UIButtons (custom type) on subview which is custom view and none of the buttons is recognising the action even though I set the target. I have to do it programatically.
I have tried setting isUserInteractionEnabled but it is not working. Buttons are on the view, respecting the bounds.
Here, viewDidLoad from InitialViewController:
override func viewDidLoad()
{
super.viewDidLoad()
self.questionView?.firstanswer!.isEnabled = true
self.questionView?.firstanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.secondanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.thirdanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.fourthanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
}
Here is the action function:
#objc func answerTheQuestion(_sender:UIButton) {
print("aa")
if let questionsAnswers = self.quizzes?.quizzes[self.randomNumber!]["questions"] as? [[String:Any]] {
if (questionsAnswers[self.randomQuestion!]["question"] as? String) != nil {
if let correctAnswer = questionsAnswers[self.randomQuestion!]["correct_answer"] as? String {
if _sender.titleLabel?.text == correctAnswer {
_sender.backgroundColor = UIColor.green
} else {
_sender.backgroundColor = UIColor.red
}
}
}
}
}
View and buttons are added normally, only tap is not working.
It should go red when the answer is wrong, and green when it is right. Questions and everything else is added normally, but it even won't print "aaa" in the beginning of the target function. Pls help, thanks!!

Swift 4 - UIRefreshControl on vertical UICollectionView lags

For some reason, my pull to refresh is really hard to complete. What I mean by that, is that in order to pull-to-refresh I have to begin from the very top of my collection view and scroll down to the very bottom... sometimes I even have to use a second finger in order to scroll more to make it work!
Here's how I initialise the refresher:
private var refresher: UIRefreshControl!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
refresher = UIRefreshControl()
refresher.addTarget(self, action: #selector(self.requestRefreshContent), for: .valueChanged)
if #available(iOS 10.0, *) {
schoolPostsCollectionView.refreshControl = refresher
}
else {
schoolPostsCollectionView.addSubview(refresher)
}
refresher.beginRefreshing()
}
Here's how I call beginRefreshing():
private func getContentOfSchool() {
someBackgroundServerCall() {
// some code
...
DispatchQueue.main.async {
self.refresher.endRefreshing()
self.schoolPostsCollectionView.reloadData()
}
}
}
Any idea why is this happening?
try this one....
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Refreshing...", attributes: nil)
refresher.tintColor = UIColor.black
refresher.addTarget(self, action: #selector(self.requestRefreshContent), for: .valueChanged)
if #available(iOS 10.0, *) {
schoolPostsCollectionView.refreshControl = refresher
} else {
schoolPostsCollectionView.backgroundView = refresher
}

swift GestureRecognizer in cells

I would like to make long press tableview Cells, But i'm getting error:
UIGestureRecognizer.Type' does not have a member named 'state'
Here's the code
override func viewDidLoad() {
super.viewDidLoad()
var gesture: UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
gesture.minimumPressDuration = 2.0
self.view.addGestureRecognizer(gesture)
}
func longpressed() {
if(UIGestureRecognizer.state == UIGestureRecognizerState.Ended){
print("ended")
} else if (UIGestureRecognizer.state == UIGestureRecognizerState.Began){
print("began")
}
}
And Yes I've created Bridging-Header.h and imported this file:
#import <UIKit/UIGestureRecognizerSubclass.h>
I want swift tutorial not objective-c!
Add a gesture recogniser to your UITableView like
var gestureRec = UILongPressGestureRecognizer(target: self, action: "didTap:")
self.tableView.addGestureRecognizer(gestureRec)
Implement a didTap function, which would look something like this.
func didTap(sender : UIGestureRecognizer)
{
if sender.state == .Began {
var location = sender.locationInView(self.tableView)
var indexPath = self.tableView.indexPathForRowAtPoint(location)
var cell = self.tableView.cellForRowAtIndexPath(indexPath!)
}
}
This should work.
Try this in your longPress method:
func longpressed(sender: UILongPressGestureRecognizer) {
var state = sender.state
if(state.state == UIGestureRecognizerState.Ended){
print("ended")
} else if (state.state == UIGestureRecognizerState.Began){
print("began")
}
}

Swift - validating UITextField

I have these outlets in my app:
#IBOutlet var name1: UITextField!
#IBOutlet var name2: UITextField!
#IBOutlet var name3: UITextField!
#IBOutlet var name4: UITextField!
#IBOutlet var newButton: UIButton!
What I tried to do is the following:
Every time the user types something in one of these four UITextFields or deletes something, I want to check if any UITextField is empty
If any UITextField is empty, the button should be disabled.
If all UITextFields are set (not empty), the button should be enabled.
My code:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
setButton()
return true
}
func setButton() {
let inputValid = checkInput()
if inputValid {
newButton.enabled = true
} else {
newButton.enabled = false
}
}
func checkInput() -> Bool {
let name1Value = name1.text
let name2Value = name2.text
let name3Value = name3.text
let name4Value = name4.text
if !name1Value.isEmpty && !name2Value.isEmpty && !name3Value.isEmpty && !name4Value.isEmpty {
return true
}
return false
}
Ok, it works 50% for now.
When I type one character in each UITextField, the button is still disabled.
When I add a second one to any UITextField, the button gets enabled etc...
Can anyone help me with this?
Alternatively, you can use this, which is called every time a key is pressed:
name1.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
name2.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
name3.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
name4.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
func textFieldDidChange(textField: UITextField) {
if name1.text?.isEmpty || name2.text?.isEmpty || name3.text?.isEmpty || name4.text?.isEmpty {
//Disable button
} else {
//Enable button
}
}
Swift 4
- Here is how I have solved it trying to avoid long conditionals
- This will also allow you to do realtime validation on each individual textfield, unlike the accepted answer, you can update your UI according to what the user is typing.
let textfields : [UITextField] = [name1, name2, name3, name4]
for textfield in textfields {
textfield.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
}
#objc func textFieldDidChange(_ textField: UITextField) {
//set Button to false whenever they begin editing
yourButton.isEnabled = false
guard let first = textFields[0].text, first != "" else {
print("textField 1 is empty")
return
}
guard let second = textFields[1].text, second != "" else {
print("textField 2 is empty")
return
}
guard let third = textFields[2].text, third != "" else {
print("textField 3 is empty")
return
}
guard let forth = textFields[3].text, forth != "" else {
print("textField 4 is empty")
return
}
// set button to true whenever all textfield criteria is met.
yourButton.isEnabled = true
}
The textField:shouldChangeCharactersInRange: method gets called BEFORE the contents of the text field have changed.
You should special-case the current text field and figure out if it's new contents are going to be blank after the edit.
Something like this:
textField.text.length > range.length - replacementString.length
(That's off the top of my head, and not debugged. Plus you would have to come up with logic that makes sure all the other fields are non-blank, and use the logic above to test the contents of the current field.)
Take a look at UITextFieldValidator. I have created a validator which covers almost each validation required in an app. Also its in swift. So go ahead and check it out.
Try this code. Hope you will get what to do.
func updateSaveButtonState() {
let text = titleTextField.text ?? ""
saveButton.isEnabled = !text.isEmpty
}
#IBAction func textEditingChanged(_ sender: UITextField) {
updateSaveButtonState()
}
#IBAction func returnPressed(_ sender: UITextField) {
titleTextField.resignFirstResponder()
}
Swift 4 & 5
Firstly, you create a function like setupTextFields() and you call it in viewDidLoad() (something like this):
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupTextFields() //You call the function here.
}
func setupTextFields() {
name1.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)
name2.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)
name3.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)
name4.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)
}
Then you create another function which each time you press a key, that function will be called. I'll show you two options, then you choose which fits better for you. Usually, Option 1 would be considered a better implementation for Swift.
Option 1
#objc func textFieldDidChange(_ textField: UITextField) {
guard !name1.text!.isEmpty else {
button.isEnabled = false
return
}
guard !name2.text!.isEmpty else {
button.isEnabled = false
return
}
guard !name3.text!.isEmpty else {
button.isEnabled = false
return
}
guard !name4.text!.isEmpty else {
button.isEnabled = false
return
}
button.isEnabled = true
}
Option 2
#objc func textFieldDidChange(_ textField: UITextField) {
if name1.text!.isEmpty || name2.text!.isEmpty || name3.text!.isEmpty || name4.text!.isEmpty {
button.isEnabled = false
} else {
button.isEnabled = true
}
}