What is missing from this minimal UITextFieldDelegate implementation, to cause crashing? - swift

The crash occurs upon selecting the Text Field in the simulator. The debugger seems to tell me nothing useful.
import UIKit
class TextField: NSObject, UITextFieldDelegate {}
In the View Controller:
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = TextField()
}
#IBOutlet weak var textField: UITextField! // assigned in IB.

You can't set the delegate to TextField()
Just set the delegate to self, because you use the UITextFieldDelegate in your class:
textField.delegate = self

UITextField.delegate is unowned, so the delegates were being deallocated after viewDidLoad returned.

Assign the delegate to a property instead
first add customTextFieldDelegate as a property
var customTextFieldDelegate = TextField()
and in ViewDidload
self.textField.delegate = self.customTextFieldDelegate

Related

Best way to handle textViewChanged in Swift 5.5

I'm trying to add attributed strings to some text in a UITextView on text change in Swift 5.5
What's the best approach, a UIView or a UIViewController?
Sample code would really help me out as I can't seem to get either approach to work atm.
Thanks
class ViewController: UIViewController, UITextViewDelegate { //If your class is not conforms to the UITextViewDelegate protocol you will not be able to set it as delegate to UITextView
#IBOutlet weak var bodyText: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
bodyText.delegate = self //Without setting the delegate you won't be able to track UITextView events
}
func textViewDidChange(_ textView: UITextView) { //Handle the text changes here
print(textView.text); //the textView parameter is the textView where text was changed
}
}
#Rob Hope this boilerplate works for you :)

Unexpectedly found nil in swift with UIProgressView

I've created a progressView and linked it like this:
And here is what I do in my view controller:
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
#IBOutlet weak var progressView: UIProgressView!
#IBOutlet weak var KronosWebsite: WKWebView!
override func loadView() {
//initialize the webview
progressView = UIProgressView()
progressView.progress = 1.0
KronosWebsite = WKWebView()
self.view = KronosWebsite
self.view.addSubview(progressView)
}
}
And I've got
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional
in this line progressView.progress = 1.0
Add super.loadView() when you use loadView for a vc that originally inside storyboard
override func loadView() {
super.loadView()
or insert all code inside viewDidLoad , also don't re-init
progressView = UIProgressView()
KronosWebsite = WKWebView()
as they already initiated from storyboard
The docs say to never override loadView if your view controller comes from a storyboard or xib:
loadView()
If you use Interface Builder to create your views and initialize the view controller, you must not override this method.
Everything that you're currently doing in loadView can be done in the storyboard anyway, so just remove the loadView method and connect your UIProgressView and WKWebView to your outlets in your storyboard. You can also set the progress view's initial progress to 1.0 inside the storyboard.

How to focus on a text field when opening an application?

How to focus on a text field when opening an application?
Swift 4,
Xcode 10,
macOS
ANSWER:
Thanks to the advice by #Willeke in the comments, I did it this way:
import Cocoa
import AppKit
import Foundation
let defaults = UserDefaults.standard
class ViewController: NSViewController{
#IBOutlet weak var addDomain: NSTextField!
#IBOutlet weak var addSiteField: NSTextField!
#IBOutlet weak var tableView: NSTableView!
#IBOutlet weak var removeSite: NSSegmentedControl!
override func viewDidAppear() {
super.viewDidAppear()
addDomain.window?.makeFirstResponder(addDomain)
}
Because:
https://developer.apple.com/documentation/appkit/nsresponder/1526750-becomefirstresponder
Use the NSWindow makeFirstResponder(_:) method, not becomeFirstResponder() method, to make an object the first responder. Never invoke this method directly.
You seem to be not over-riding the viewDidAppear that belongs to your NSViewController, but you are adding a new function on it's own.
Try using:
override func viewDidAppear() {
// Though the default implementation does nothing as of now,
// it is always safe to have the call to the super function in place,
// in case you plan to add sub-classes in between.
super.viewDidAppear()
addDomain.window?.makeFirstResponder(addDomain)
}
In your viewController in viewDidAppear
yourTextField.becomeFirstResponder()
Update:
macOS implementation requires using NSWindow makeFirstResponder!

Keyboard not being dismissed

I realize this is a trivial question with tons of answer on SO. I may just need a pair of fresh eyes as I've triple checked everything and cannot see where I am going wrong with this. I just want to dismiss the keyboard on hitting the return key. I'm setting the delegate properly and implementing the proper methods, so why won't the keyboard dismiss?
Does having a collectionView in the viewController complicate things? (text field is NOT inside collectionView)
class SearchController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITextFieldDelegate {
#IBOutlet weak var searchBar: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
setupUI()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
searchBar.resignFirstResponder()
return true
}
Things I've tried:
cleaning the project
restarting xcode
changing the searchBar.resignFirstResponder() to textField.resignFirstResponder()
setting the delegate for the text field inside IB instead of in viewDidLoad
What the heck am i missing here!?
You need to implement the proper text field delegate method. There is no such delegate method as textFieldShouldReturn(textField:). The proper method is textFieldShouldReturn(_:).
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
searchBar.resignFirstResponder()
return false
}
The _ makes a huge difference. You may have copied an old Swift 2 implementation.
It's best to let Xcode perform code completion to ensure you get the correct signature of any method you are implementing or calling.
Use this code
view.endEditing(true)

My scrollViewDidScroll function is not receiving calls

I'm trying to check if a user is scrolling up and down on my app but it's not calling my scrollViewDidScroll method
Any ideas why it's not printing received scroll when I scroll up and down on the app?
import UIKit
class CreateAccount: UIViewController, UITextFieldDelegate, UIScrollViewDelegate {
#IBOutlet weak var scrollViewer: UIScrollView!
#IBOutlet weak var usernameTextField: UITextField!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var reenterPasswordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func scrollViewDidScroll(scrollView: UIScrollView) {
print("received scroll")
}
}
Add the scrollview delegate. Whenever you implement a delegate method you need tell it what controller to use, usually it will be self. It's caught me out a few times.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
scrollViewer.delegate = self
}
You need to set delegate of scrollview also don't use tag to differentiate 2 scrollview instead of that create 2 outlets of scrollview and use that in UIScrollViewDelegate methods like this.
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView == scrollView1 {
print("received scrollview 1")
}
else if scrollView == scrollView2 {
print("received scrollview 2")
}
}
Delegate are given properly even if your scrollview delegate method not calling then please check you delegate method which you have added for scrollview, this may give warning due to using old swift version scrollview delegate with swift 4.0
Please correct it with below if this is the case:
Old Method:
func scrollViewDidScroll(scrollView: UIScrollView) {
}
New Method:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
}
You can set the .delegate = self as Sarcoma suggests, or:
CTRL drag from scrollView in storyboard onto the File Owner (it is located in the view hierarchy list, actually it is right by the yellow circle icon by the name of your controller: [O] Create Account and choose
delegate