Passing Data from ViewController to UITableViewController - ios

Help me to understand what I am missing please?
Storyboard setup:
ViewController -> TabBarController -> NavigationController which contains a TableViewController
There is a segue with Identifier "startUp" from the ViewController to the TabBarController
The ViewController is the Initial Entry Screen.
The ViewController has a SegmentedControl and a Button
USAGE: User selects one of the segments and presses the button. The view should segue to the TableViewController and replace the NavigationItem.Title with the title from the SegmentedControl segment which was selected.
PROBLEM: The data is not being passed from the ViewController to the TableViewController (and through the TabBarController and NavigationController). I am always ending up with a blank Header Title on the TableViewController. I have walked carefully through a couple dozen 'how-tos' over the past few days both here and other locations on the web using segue and other methods. At this point nothing seems to work and I'm dizzy (and probably missing something really, really basic).
Here is the way the code currently 'sits'
ViewController Code:
import UIKit
class ViewController: UIViewController {
var someData: String? = ""
#IBOutlet weak var cpChoice: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func startBut(_ sender: Any) {
performSegue(withIdentifier: "startUp", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let theIndex = cpChoice.selectedSegmentIndex
someData = cpChoice.titleForSegment(at: theIndex)
print(someData!) //outputs correctly to console
if segue.destination is CheckpointVC
{
let vc = segue.destination as? CheckpointVC
vc?.data = someData!
}
}
}
TableViewController Code:
import UIKit
class CheckpointVC: UITableViewController {
var data: String = ""
#IBOutlet weak var theHeader: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = data
//theHeader.title = data
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
}

Did you breakpoint on the segue to actually check if segue.destination is CheckpointVC? The solution has been right in front of your eyes all along. Since you have setup the viewcontrollers as such...
ViewController -> TabBarController -> NavigationController which contains a TableViewController
Your segue.destination is technically TabBarController unless the segue with identifier startUp leads to TableViewVC.
A short way to solve it is to unwrap the TableVC from your TabBarVC as such:
(tabBarVC.viewControllers[indexOfYourNavVC] as? NavigationController).viewControllers.first as? TableVC)
The longer but cleaner way of doing it is to implement a routing pattern from this blog. Sorry to say that I myself am still learning about this so I can only recommend websites to start with:
https://clean-swift.com/routing-in-clean-swift/

Just replace the segue target to a Navigation Controller Which contain your CheckpointVC as a root view controller.

The solution
PIECE DEFINITIONS
ViewController.swift
import UIKit
class ViewController: UIViewController {
var someData: String? = ""
#IBOutlet weak var cpChoice: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func startBut(_ sender: Any) {
performSegue(withIdentifier: "startUp", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//get the string representing the segment chosen and assign it to someData
let theSegmentChosen = cpChoice.selectedSegmentIndex
someData = cpChoice.titleForSegment(at: theSegmentChosen)
let barVC = segue.destination as! UITabBarController //
let navigationControllerDestination = barVC.viewControllers?[0] as? navVC //the array index [0] indicates the first view controller belonging to the TabBarController
let firstViewControllerOfNavigationController = navigationControllerDestination?.topViewController as! CheckpointVC
firstViewControllerOfNavigationController.data = someData!
}
}
TabBarVC
import UIKit
class TabBarVC: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
NavVC
import UIKit
class navVC: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
CheckpointVC.swift
import UIKit
class CheckpointVC: UITableViewController {
//the variable we'll pass the data to from the starting viewcontroller
var data: String = ""
#IBOutlet weak var theHeader: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
theHeader.title = data
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 10
}
}

Related

Add items to another view controller table view on button click

I have a view controller called ListViewController and another called AddFoodViewController. In ListViewController users are able to add their own ingredients to the grocery list which is presented in a table view. When they go to the AddFoodViewController, users should be able to click a button which says "add to list" which will add the array of ingrediets (that are already presented in a table view) into the grocery list. I am new to this, so I was wondering if anyone can help? I have successfully been able to get the ListViewController to work, however I am not sure how to add the array of ingredients from AddFoodViewController into the previous ListViewController.
class AddFoodViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
#IBOutlet weak var FoodTableView: UITableView!
#IBOutlet weak var sendFoodBtn: UIButton!
//array of food
let array = ["1 Salad", "3oz Chicken", "2 Tomatoes", "2 Cucumbers"]
let category = ""
override func viewDidLoad() {
super.viewDidLoad()
}
//display array in table view
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return(array.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let foodCell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "foodCell")
foodCell.textLabel?.text = array[indexPath.row]
foodCell.backgroundColor = .clear
foodCell.textLabel?.textColor = .darkGray
foodCell.textLabel?.font = UIFont(name: (foodCell.textLabel?.font.fontName)!, size:17)
return foodCell
}
//button that is supposed to add all ingredients to the ListViewController
#IBAction func addOnClick(_ sender: Any) {
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "toList"){
let vc = (segue.destination as! ListViewController)
vc.category = array
}
}
}
Passing data to previous view controller can be implemented by delegation pattern, first at all, declare a protocol in your AddFoodViewController, and define a delegate property in view controller.
// AddFoodViewController.swift
protocol AddFoodViewControllerDelegate {
func addIngredient(array: [String])
}
class AddFoodViewController: UIViewController {
...
var delegate: AddFoodViewControllerDelegate?
// MARK: add function
func actionAdd() {
delegate?addIngredient(array)
}
...
}
Back to your ListViewController,find the segue destination view controller which is your AddFoodViewController (remember to assign its class name in the storyboard), and assign delegate to self.
// ListViewController.swift
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
...
let vc = segue.destination as? AddFoodViewController
vc?.delegate = self
...
}
// in the same file, implement delegate method here
extension ListViewController: AddFoodViewControllerDelegate {
func addIngredient(array: [String]) {
items += array
// do table reload or something
}
}

how to modify an array from another class

Im making to do list-app which consist of 2 View Controllers
one with table view hold an array and display it and second one with a textField, a button function to append the text field's text to the array
to display the new appended string it in the first view controller
heres my code:
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var exmpArray = ["DDDD","rrr","TTT"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func addBtnBar(_ sender: Any) {
performSegue(withIdentifier: "showMe", sender: nil)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return exmpArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
cell?.textLabel?.text = exmpArray[indexPath.row]
return cell!
}}
and the second one is:
class SecondViewController: UIViewController {
#IBOutlet weak var myTextField: UITextField!
var realAry:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
}
let myObj = ViewController()
#IBAction func addBtn(_ sender: Any) {
myObj.exmpArray.append(myTextField.text!)
print(myObj.exmpArray)
}
after appending the new words it doesn't display in the first controller
One problem is this line:
let myObj = ViewController()
That creates a new instance of ViewController that has nothing to do with the view controller that called you. Get rid of that line. It's wrong.
You need to set up a delegate property in SecondViewController that points back to ViewController, define a protocol for that delegate to conform to, and use that protocol so that SecondViewController can notify it's delegate when the array changes.
In ViewController, add a prepareForSegue() function that takes the destination view controller, casts it to type SecondViewController, and sets SecondViewController's delegate to self.
Both arrays are different you are just copying first VC array to 2nd VC array. Array is value type in swift. Instead of creating 2 arrays make 1st VC array as static.
static var exmpArray = ["DDDD","rrr","TTT"]
Now you can use & update this in all VC by calling like below
FirstVC.exmpArray

how to perform segue to a VC with Container

see this gif
when I choose the city Med , it passed to the TableVC not to the FirstVC (MainVC)
can I do that ? segue to the mainVC with the data passed through
the container (TableVC) ?
here what I did so far
MainVC
Empty
TableVC
import UIKit
class passedViewController: UITableViewController {
#IBOutlet weak var passcelltow: UITableViewCell!
#IBOutlet weak var passcell: UITableViewCell!
var passedCity1 = "اختر المدينة الاولى"
var passedCity2 = "اختر المدينة الثانية"
override func viewDidLoad() {
super .viewDidLoad()
passcell.textLabel?.text = passedCity1
passcelltow.textLabel?.text = passedCity2
}
}
Table 1 with data to pass to the TableVC
import UIKit
class city2ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
var city2 = ["RUH" , "Med" , "Jed"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return city2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
print(indexPath.row)
cell.textLabel?.text = city2[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "show", sender: city2[indexPath.row])
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let passing = segue.destination as! passedViewController
passing.passedCity2 = sender as! String
}
}
Table 2 is the same ..
commend error
0 1 2 Could not cast value of type 'UIViewController' (0x107a10288) to
'table_view_test_pass.passedViewController' (0x105dbfdf8). (lldb)
You can pass data via segues or protocols. Since you are using segues i will show you a complete example and how to do it the right way in Swift 3. Using only two ViewControllers.
Create two UITextFields in the main "ViewController".
Create a new view controller of type UIViewController call it "MainTabelViewController" and add a tableView in it. Select content Dynamic prototypes Style Grouped and create 1 prototype cell and add a UILabel to it for the city name. "Don't forget the put the cell identifier name". I called it "cell".
Add the delegates and data sources to the class and add its functions like in code.
Create a segue from the main view controller to the main table view controller. And create another segue the opposite direction. "Don't forget the put the segue identifier names" I called them "toCity" & "toMain"
Create a "CityTableViewCell" controller of type UITableViewCell and create an IBOutlet of UILabel type where you will save the city name in as a text.
Edit this part in the AppDelegate.swift To delete the city names saved using in the UserDefaults every time the app is launched. So i wont populate the UITextFields randomly every time.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var userDefaults: UserDefaults!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "City One")
userDefaults.removeObject(forKey: "City Two")
return true
}
This is the ordinary main ViewController.swift where you have your UITextFields in. I distinguish which UITextField did the user click on using the tags. You need to add also the UITextFieldDelegate protocol to be able to use the the textFieldDidBeginEditing function. And i also save the selected city names using UserDefaults class to call them when user chooses the other city.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var cityOneLabel: UITextField!
#IBOutlet var cityTwoLabel: UITextField!
#IBOutlet var continueButton: UIButton!
var selectedCityOne = ""
var selectedCityTwo = ""
var userDefaults: UserDefaults!
override func viewDidLoad() {
super.viewDidLoad()
cityOneLabel.delegate = self
cityTwoLabel.delegate = self
cityOneLabel.tag = 1
cityTwoLabel.tag = 2
continueButton.isEnabled = false
}
override func viewDidAppear(_ animated: Bool) {
userDefaults = UserDefaults.standard
cityOneLabel.text = selectedCityOne
cityTwoLabel.text = selectedCityTwo
if selectedCityOne != "" {
userDefaults.set(selectedCityOne, forKey: "City One")
} else {
cityOneLabel.text = userDefaults.string(forKey: "City One")
}
if selectedCityTwo != "" {
userDefaults.set(selectedCityTwo, forKey: "City Two")
} else {
cityTwoLabel.text = userDefaults.string(forKey: "City Two")
}
if cityOneLabel.text != "" && cityTwoLabel.text != "" {
continueButton.isEnabled = true
} else {
continueButton.isEnabled = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func continueButtonAction(_ sender: UIButton) {
//Later on continue after selecting the cities
}
func textFieldDidBeginEditing(_ textField: UITextField) {
performSegue(withIdentifier: "toCity", sender: textField.tag)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toCity" {
guard let cityVC = segue.destination as? MainTableViewController else {
return
}
cityVC.selectedTextField = sender as! Int
}
}
}
In the CityTabelViewCell.swift add the IBOutlet UILabel for the city name.
import UIKit
class CityTableViewCell: UITableViewCell {
#IBOutlet var cityNameLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
For the MainTabelViewController.swift write this:
Here is where i create an array of strings to populate my table view UILabels with.
import UIKit
class MainTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var cityTabelView: UITableView!
var cityNamesArray = ["Cairo", "Alexandria", "Suez"]
var selectedTextField = Int()
var selectedCityName = ""
override func viewDidLoad() {
super.viewDidLoad()
cityTabelView.delegate = self
cityTabelView.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CityTableViewCell
cell.cityNameLabel.text = cityNamesArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cityNamesArray.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedCityName = cityNamesArray[indexPath.row]
performSegue(withIdentifier: "toMain", sender: self)
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
var title = ""
if selectedTextField == 1 {
title = "City One"
} else if selectedTextField == 2 {
title = "City Two"
}
return title
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toMain" {
guard let mainVC = segue.destination as? ViewController else {
return
}
if selectedTextField == 1 {
mainVC.selectedCityOne = selectedCityName
} else if selectedTextField == 2 {
mainVC.selectedCityTwo = selectedCityName
}
}
}
}
This is how my layout looks like. Try it. I just added a continue button too if the user will have to go to another UIViewController after selecting the two cities.
If you want to segue to MainVC, you should instantiate a view controller from that class in prepare for segue.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let passing = segue.destination as! ViewController
passing.passedCity2 = sender as! String
}
Change ViewController to whatever the name of your class is for MainVC.
If you want to go back to the Parent View, you should be using an unwind-segue.
For that you must create the unwind segue method in the Parent View like this
#IBAction func unwindSegueFromChild(segue: UIStoryboardSegue){
// This code executes when returning to view
}
And in your child view you must create the unwind segue ctrl+dragging
There a dropdown appears and you select unwindSegueFromChild
Once you've done that, you must assign the unwind segue an identifier and programmatically perform it like a normal segue.

How to pass data between container view and main view controller properly

I'm dealing with following problem: On main VC I have a TableView, and on container view controller I have a textField. I want to add every text, I'm typing in container automatically appears as a new row on tableView in main VC
By now I'm using segue to send data from main VC to container. But what should I implement to do the same in a reverse order? I though of implementing delegate of main VC in my container view, but I have no idea how to do that properly. Or maybe there is exist more common solution.
Anyway, here is my code:
class MessageViewController: UIViewController {
var currentUser: User!
var containerViewController: InputTextViewController?
#IBOutlet weak var enterMessageView: UIView!
#IBOutlet weak var messageTableView: UITableView!
}
extension MessageViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "moveToInputText" {
let connectContainerViewController = segue.destination as? InputTextViewController
containerViewController = connectContainerViewController
containerViewController?.userSendMessageTo = currentUser
}
}
}
extension MessageViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return currentUser.mesaageHistory.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "messageCell") as! ChatMessageTableViewCell
let data = currentUser.mesaageHistory[indexPath.row]
cell.messageLabel.text = data.messageText
return cell
}
}
class InputTextViewController: UIViewController {
#IBOutlet weak var messageTextField: UITextField!
var userSendMessageTo: User!
weak var delegate = MessageViewController()
#IBAction func sendMessge(_ sender: Any) {
handleSend()
userSendMessageTo.mesaageHistory.append(message)
print(userSendMessageTo.mesaageHistory[0].messageText)
let row = userSendMessageTo.mesaageHistory.count - 1
let insertIndexPath = IndexPath(item: row, section: 0)
print(userSendMessageTo.mesaageHistory.count)
delegate?.messageTableView.beginUpdates()
delegate?.messageTableView.insertRows(at: [insertIndexPath], with: UITableViewRowAnimation.automatic)
delegate?.messageTableView.endUpdates()
}
}
Here's how to use the 'delegate' pattern properly
Protocol declaration & delegate member
protocol InputTextViewControllerDelegate: class {
func someFunc()
func anotherFunc()
}
class InputTextViewController: UIViewController {
weak var delegate: InputTextViewControllerDelegate?
}
Protocol implementation & setting the delegate property
extension MessageViewController, InputTextViewControllerDelegate {
// MARK: InputTextViewControllerDelegate
//
func someFunc()
{
}
func anotherFunc()
{
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "moveToInputText" {
let connectContainerViewController = segue.destination as? InputTextViewController
containerViewController = connectContainerViewController
containerViewController
}
}
}

Get value from Modal View in Swift iOS

i'm trying to start writing Swift and i'm trying to get a value from a modal view controller with no luck.
I have two controllers, the ViewController and modalViewController.
In ViewController i have a UITableView and with a press of a button i open the modalViewController.
Then from a UITextField i pass the value.
I have implement a protocol with delegate and func but somewhere i'm missing something or had it wrong.
ViewController.swift
import UIKit
class ViewController: UIViewController,UITableViewDelegate,modalViewControllerDelegate{
#IBOutlet var table: UITableView!
var tableData = ["First Row","Second Row","Third Row"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(animated: Bool) {
table.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(table:UITableView?,numberOfRowsInSection section: Int) -> Int
{
return tableData.count
}
func tableView(table:UITableView?,cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let cell:UITableViewCell = UITableViewCell(style:UITableViewCellStyle.Default,reuseIdentifier:"cell")
cell.textLabel?.text = tableData[indexPath.row]
return cell
}
func sendText(text: NSString) {
tableData.append(text)
} }
modalViewController.swift
import UIKit
protocol modalViewControllerDelegate {
func sendText(var text: NSString)
}
class modalViewController: UIViewController{
let delegate: modalViewControllerDelegate?
#IBOutlet var textField: UITextField?
#IBAction func cancelButton(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func saveButton(sender: AnyObject) {
delegate?.sendText(self.textField!.text)
dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
I have no errors in the code, the delegate is not working, it's always nil.
Thanks.
You have to assign the delegate in your first view controller.
Also, you have to change let delegate: modalViewControllerDelegate? to a var, or else you can't change it.
Right now your delegate is empty.
It's unclear how you're accessing ModalViewController. If you're using segues:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "modalViewControllerSegue" {
var destination = segue.destinationViewController as CategoryViewController
destination.delegate = self
}
}
Or if you're doing it programmatically:
var modalViewController = ModalViewController(parameters)
modalViewController.delegate = self
presentViewController(modalViewController, animated: true, completion: nil)
Storyboard identifier:
let destination = UIStoryboard.mainStoryboard().instantiateViewControllerWithIdentifier("ModalViewController") as ModalViewController
delegate = self
showViewController(destination, sender: nil)
EDIT:
If you want to access ModalViewController by selecting a cell you need the tableView: didSelectRowAtIndexPath method:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("modalViewControllerSegue", sender: self)
}
Using this, you'll need the method prepareForSegue to set the delegate.
You have to set your modalViewController's delegate property before presenting it. If you're using segues, you can do this in prepareForSegue(_:).
Also, class names should begin with uppercase letters (modalViewController should be ModalViewController). Only instances should begin with lowercase letters.
Another option, instead of using delegation, is to use an unwind segue. Here's a tutorial: http://www.cocoanetics.com/2014/04/unwinding/
In your case, in your presenting view controller you could have the method:
func returnFromModalView(segue: UIStoryboardSegue) {
// This is called when returning from the modal view controller.
if let modalVC = segue.sourceViewController as? ModalViewController
where segue.identifier == "mySegueID" {
let text = modalVC.textField.text
// Now do stuff with the text.
}
}
And then just link up everything in the Interface Builder as shown in the tutorial.

Resources