Q:

Custom delegate nil and not saving userDefaults

I make a delegate inside UIView to passed data to my controller and than I save it in userdefaults. but when I try to save it, it return nil. How can I save it and not return nil.
this is my code in UIView and my protocol
protocol SaveUpdateInputDelegate {
   func saveInputText()
   func fetchInputText()
}

class FormUIView: UIView {

var delegate: SaveUpdateInputDelegate?

let nameLabel = ProfileCustomLabel(textName: "Name")
let nameTextField = CustomTextField(placeholderName: "Name")

let emailLabel = ProfileCustomLabel(textName: "Email")
let emailTextField = CustomTextField(placeholderName: "Email")

let titleLabel = ProfileCustomLabel(textName: "Title")
let titleTextField = CustomTextField(placeholderName: "Title")

let locationLabel = ProfileCustomLabel(textName: "Location")
let locationTextField = CustomTextField(placeholderName: "Location")

this is my controller code that have a button to save the input text and save it in userdefaults
class ProfileController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, SaveUpdateInputDelegate {

// I need to initialized this to create autolayout
let formView: FormUIView = FormUIView()

let saveButton: UIButton = {
    let btn = UIButton(type: .system)
    btn.setTitle("Save", for: .normal)
    btn.setTitleColor(.white, for: .normal)
    btn.backgroundColor = #colorLiteral(red: 0.1254901961, green: 0.7411764706, blue: 1, alpha: 1)
    btn.layer.cornerRadius = 18
    btn.addTarget(self, action: #selector(handleSave), for: .touchUpInside)
    return btn
}()

override func viewDidLoad() {
    super.viewDidLoad()
    formView.delegate = self
    handleSave()
}

@objc func handleSave() {
    print("saved...")
    guard let data = UserDefaults.standard.object(forKey: "profileImageEditedKey") as? Data else { return }
    let image = UIImage.init(data: data)
    DispatchQueue.main.async {
        self.profileImageView.image = image?.withRenderingMode(.alwaysOriginal)
    }

    saveInputText()
    fetchInputText()
}

func saveInputText() {
    UserDefaults.standard.set(formView.nameTextField.text!, forKey: "nameTextFieldKey")
    UserDefaults.standard.set(formView.emailTextField.text!, forKey: "emailTextFieldKey")
    UserDefaults.standard.set(formView.titleTextField.text!, forKey: "titleTextFieldKey")
    UserDefaults.standard.set(formView.locationTextField.text!, forKey: "locationTextFieldKey")
    UserDefaults.standard.synchronize()
}

func fetchInputText() {
    let name = UserDefaults.standard.value(forKey: "nameTextFieldKey") as? String ?? ""
    let email = UserDefaults.standard.value(forKey: "emailTextFieldKey") as? String ?? ""
    let title = UserDefaults.standard.value(forKey: "titleTextFieldKey") as? String ?? ""
    let location = UserDefaults.standard.value(forKey: "locationTextFieldKey") as? String ?? ""

    formView.nameTextField.text = name
    formView.emailTextField.text = email
    formView.titleTextField.text = title
    formView.locationTextField.text = location
}

A:

You should call only fetchInputText in viewDidLoad just to set the textFields text from the UserDefaults. Currently you are calling handleSave which internally calls saveInputText when textFields have no values(or default values). It might crash if you haven't put any default text in Storyboard/Xib for any of these textFields.,
override func viewDidLoad() {
    super.viewDidLoad()
    formView.delegate = self

    fetchInputText()
}

And the purpose of using delegate does not look meaningful because the FormUIView is not propagating anything for delegate to handle. This might be wrong as i don't know the complete implementation of FormUIView.

