I have mainVC with 4 labels and 4 goToVC buttons, each button use segue to present another 1 of 4 VC. Every vc have textField and doneButton. I want to show text from textField in mainVC labels and i want to use delegates. But instead i got empty labels. Please help.
Delegate.swift
protocol TextFieldDelegate {
func didFinishTextField(text: String)
}
MainVC.swift
class MainViewController: UIViewController, TextFieldDelegate {
#IBOutlet weak var redText: UILabel!
#IBOutlet weak var orangeText: UILabel!
#IBOutlet weak var pinkText: UILabel!
#IBOutlet weak var purpleText: UILabel!
var choosenLabel: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toRedVC" {
let vc = segue.destination as! RedViewController
vc.delegate = self
choosenLabel = redText
} else if segue.identifier == "toOrangeVC" {
let vc = segue.destination as! OrangeViewController
vc.delegate = self
choosenLabel = orangeText
} else if segue.identifier == "toPinkVC" {
let vc = segue.destination as! PinkViewController
vc.delegate = self
choosenLabel = pinkText
} else if segue.identifier == "toPurpleVC" {
let vc = segue.destination as! PurpleViewController
vc.delegate = self
choosenLabel = purpleText
}
}
func didFinishTextField(text: String) {
if let data = choosenLabel {
data.text = text
}
}
#IBAction func redButton(_ sender: UIButton) {
}
#IBAction func orangeButton(_ sender: UIButton) {
}
#IBAction func pinkButton(_ sender: UIButton) {
}
#IBAction func purpleButton(_ sender: UIButton) {
}
}
RedVC(other 3 same).swift
class RedViewController: UIViewController {
var delegate: TextFieldDelegate?
var textVar: String = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func textField(_ sender: UITextField) {
if let data = sender.text {
textVar = data
}
}
#IBAction func doneButton(_ sender: UIButton) {
delegate?.didFinishTextField(text: textVar)
dismiss(animated: true, completion: nil)
}
}
Everything seems ok in your code. I suggest you to check your text field's actions are set to editingChanged in ViewController.
Related
class SigninViewController: UIViewController {
#IBOutlet weak var usernameTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
var signinAPIManager: SigninAPIManager?
override func viewDidLoad() {
super.viewDidLoad()
setupView()
setupData()
}
private func setupData() {
setupServices()
}
private func setupView() {
setupTextFields()
}
private func setupTextFields() {
let textFields = [usernameTextField, passwordTextField]
textFields.forEach{ $0?.delegate = self }
}
#IBAction func signinButton(_ sender: Any) {
signinAPIManager?.signin(optionalUsername: usernameTextField.text,
optionalPassword: passwordTextField.text)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SigninCompletedIdentifier"{
if segue.destination is HomeTableViewController{
let vc = segue.destination as? HomeTableViewController
vc?.textUser = "asds"
}
}
}
}
}
extension SigninViewController: SigninAPIManagerDelegate {
func didSigninCompletion(user: User) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondController = storyboard.instantiateViewController(withIdentifier: "secondary") as! HomeTableViewController
secondController.textUser = user.username
performSegue(withIdentifier: "SigninCompletedIdentifier", sender: self)
}
}
I want to pass user.username in extension SigninViewController to navigator withIdentifier: "SigninCompletedIdentifier"
Please try to print your object first:
print("SignInApiManager Object= ", signinAPIManager)
You'll find it nil as you haven't assigned any instance of SigninAPIManager.
Replace the following line of code:
Replace var signinAPIManager: SigninAPIManager? with var signinAPIManager: SigninAPIManager = SigninAPIManager()
I am new to Swift and was wondering on how to pass data from ViewController to ViewController that isn’t connected by segue. I have spend 2 hours on this and still can’t figure a way to do it.
Edit: The problem that I am confused on is How to take out all the stacked ViewController expect the root ViewController while being able to pass data back to the first ViewController from ViewController3 with
'navigationController?.popToRootViewController(animated: false)'
class ViewController: UIViewController, nameDelegate {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var textfield1: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Name"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc2 = segue.destination as! ViewController2
vc2.middleOfTransferingName = textfield1.text!
}
#IBAction func buttonPressed1(_ sender: Any) {
performSegue(withIdentifier: "go2", sender: self)
}
func nameThatWasEntered(name: String) {
label1.text = name
}
}
class ViewController2: UIViewController, nameDelegate {
var middleOfTransferingName: String = ""
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc3 = segue.destination as! ViewController3
vc3.transferedWithSegueLabelText = middleOfTransferingName
vc3.namePassBack = self
}
#IBAction func buttonPressed2(_ sender: Any) {
performSegue(withIdentifier: "go3", sender: self)
}
func nameThatWasEntered(name: String) {
}
}
protocol nameDelegate {
func nameThatWasEntered(name: String)
}
class ViewController3: UIViewController {
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var textfield3: UITextField!
var transferedWithSegueLabelText: String = ""
var namePassBack: nameDelegate?
override func viewDidLoad() {
super.viewDidLoad()
label3.text = transferedWithSegueLabelText
}
#IBAction func buttonPressed3(_ sender: Any) {
namePassBack!.nameThatWasEntered(name: textfield3.text!)
navigationController?.popToRootViewController(animated: false)
}
}
I found the way to transfer ViewController3 data to ViewController!
var vc3 = ViewController3()
then making ViewController as the delegate of vc3 upon loading.
override func viewDidLoad() {
super.viewDidLoad()
vc3.namePassBack = self
}
Then going back to ViewController3, I add ""vc3."" before using the delegate.
#IBAction func buttonPressed3(_ sender: Any) {
vc3.namePassBack!.nameThatWasEntered(name: textfield3.text!)
navigationController?.popToRootViewController(animated: false)
}
if you use segue then use 'Unwind segue'
for this write given code in your 'A view controller'
#IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}
In B_viewcontroller, On press button call 'Unwind segue'.
Note:- With the help of Unwind segue you can send the value for 3ed vc to 1se vc same as you send value form 1st vc to 2nd vc
for more go to this link
Im trying to pass data from a string in my popOverViewController back to my mainVC as string. But i can't figure out how to do this, so please help anyone.
My mainVC segue func :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "popoverSegue" {
let popoverViewController = segue.destinationViewController
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
popoverViewController.popoverPresentationController!.delegate = self
}
}
My popOverVC:
Im trying to pass the valueSelected back to mainVC
var pickerString = NSArray() as AnyObject as! [String]
var valueSelected = String()
#IBOutlet weak var picker: UIPickerView!
#IBAction func pickButton(sender: AnyObject?) {
// need to send valueSelected back to previous navigated view
print("Value: ", valueSelected)
dismissViewControllerAnimated(true, completion: nil)
}
need to send valueSelected string back to previous navigated view.
For this you can use closures in swift. Here is how to do this:
FirstViewController.swift
class FirstViewController: UIViewController
{
override func viewDidLoad()
{
}
#IBAction func onButtonTap(_ sender: UIButton)
{
self.performSegue(withIdentifier: "popoverSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "popoverSegue"
{
let popoverViewController = segue.destination as!PopOverViewController
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
popoverViewController.popoverPresentationController!.delegate = self
popoverViewController.completionHandler = {(valueSelected : String?) in
if let valueSelected = valueSelected
{
print(valueSelected)
//Write yout code here
}
}
}
}
}
PopOverViewController.swift
class PopOverViewController: UIViewController
{
var completionHandler : ((String?)->(Void))?
var pickerString = NSArray() as AnyObject as! [String]
var valueSelected = String()
#IBAction func pickButton(_ sender: UIButton)
{
print("Value: ", valueSelected)
self.dismiss(animated: true, completion: {[weak self] in
if let handler = self?.completionHandler
{
handler(self?.valueSelected)
}
})
}
}
If you want to use Delegate
add Protocol
protocol SelectDelegate: NSObjectProtocol {
func select(_ string: String)
}
add weak type Delegate to popOverVC and use it before dismissViewController
var pickerString = NSArray() as AnyObject as! [String]
var valueSelected = String()
weak var delegate: SelectDelegate?
#IBOutlet weak var picker: UIPickerView!
#IBAction func pickButton(sender: AnyObject?) {
print("Value: ", valueSelected)
//added Line
delegate?.select(valueSelected)
dismissViewControllerAnimated(true, completion: nil)
}
implement SelectDelegate to MainVC
class MainVC {
. . .
func select(string: String) {
//doSometing popupVC's string
}
}
assign popOverVC's delegate to mainVC
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "popoverSegue" {
let popoverViewController = segue.destinationViewController
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
popoverViewController.popoverPresentationController!.delegate = self
// added Line
popoverViewController.delegate = self
}
}
I want to the image thats in my UIImageView on my previous View after I tap on a button.
Any help? Thanks.
MainViewController.swift
class MainViewController: UIViewController {
#IBOutlet weak var hatBackground: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
hatBackground.image = UIImage(named: "black-hat-front.jpg")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPatches"{
if let childViewController = segue.destination as? ChildViewController{
}
}
}
}
ChildViewController.swift
class ChildViewController: UIViewController {
#IBOutlet weak var doubleCupButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Choose a Patch"
}
#IBAction func doubleCupButtonPressed(_ sender: AnyObject) {
hatBackground.image = UIImage(named: "badgal-hat.jpg")??
// Go back to previous Controller
navigationController?.popViewController(animated: true)
}
}
If I good understood , you want choose image in ChildViewController and show it in MainViewController. To do that you should implement delegate pattern like this:
MainViewController
class MainViewController: UIViewController, ChildViewControllerDelegate {
#IBOutlet weak var hatBackground: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
hatBackground.image = UIImage(named: "black-hat-front.jpg")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPatches"{
if let childViewController = segue.destination as? ChildViewController{
childViewController.delegate = self
}
}
}
func didSelectImage(image: UIImage?) {
self.hatBackground.image = image
}
}
ChildViewController
class ChildViewController: UIViewController {
#IBOutlet weak var doubleCupButton: UIButton!
var delegate: ChildViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Choose a Patch"
}
#IBAction func doubleCupButtonPressed(_ sender: AnyObject) {
let selectedImage = UIImage(named: "badgal-hat.jpg")
delegate?.didSelectImage(image: selectedImage)
self.navigationController?.popViewController(animated: true)
}
}
ChildViewControllerDelegate
protocol ChildViewControllerDelegate {
func didSelectImage(image:UIImage?)
}
I have a screen with a text field.
When a user inputs text into that text field, and taps out of the text field, a segue occurs.
The following screen's label text should be changed to the text entered by the user in the previous.
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var inputField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
inputField.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
inputField.resignFirstResponder()
}
func textFieldDidEndEditing(inputField: UITextField) {
let info = inputField.text
print(info)
performSegueWithIdentifier("goToBlue", sender: info)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "goToBlue" {
if let blueVC = segue.destinationViewController as? BlueViewController {
if let sentValue = sender as? String {
blueVC.receptacle = sentValue
}
}
}
}
}
The print(info) statement does not print anything
However, the segue works, but the label displays nothing.
class BlueViewController: UIViewController {
#IBOutlet weak var blueText: UILabel!
var receptacle = ""
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
blueText.text = receptacle
}
}
Clearly this has to do with timing... any ideas?
Your viewWillAppear function works first and that time your receptacle variable is not set or your label does not initialized. Try this;
#IBOutlet weak var blueText: UILabel! { didSet { blueText.text = receptacle } }
var receptacle: String? { didSet { blueText.text = receptacle } }
Change
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
blueText.text = receptacle
}
to
override func viewDidLoad() {
super.viewDidLoad()
blueText.text = receptacle
}
Don't use the sender to pass your value. The sender is only useful to check which element has started the segue, but not to pass data. Just make your info as a class-variable and pass the value like that:
var info:String!
func textFieldDidEndEditing(inputField: UITextField) {
info = inputField.text
print(info)
performSegueWithIdentifier("goToBlue", sender: info)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "goToBlue" {
if let blueVC = segue.destinationViewController as? BlueViewController {
blueVC.receptacle = info
}
}
}
Here is the very common way to do it (FYI, if the vc with inputTextfield is a popover, you can just call dismissViewController on the presenting vc)
func textFieldDidEndEditing(inputField: UITextField) {
textField.resignFirstResponder()
let info = inputField.text
print(info)
performSegueWithIdentifier("goToBlue", sender: info)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "goToBlue" {
if let blueVC = segue.destinationViewController as? BlueViewController {
blueVC.receptacle = self.inputField.text
}
}
}