I have some quite simple doubt regarding optional binding,global variable & wrapping and unwrapping . Since I am new to SWIFT, its very important to understand the tits & bits of their concepts.
1) In Swift if I declare a global variable, I have 2 options either to make it optional or non optional, so let I am having 2-4 or more optional variables . So is it advisable to optional bind all those variables in
viewDidLoad() method// so that I could use them without any problem of unwrapping and fatal error in my program.
2) Let me make myself more clear by the following example- I have 2 VC in my project VC1 & VC2 . VC2 has a text field in which user enters some value and displays it in a tabelview in VC1.
In Vc1
var namevc1 = NSMutableArray?//holds the input of textfield to be passed from VC2.
As you can see, my VC1 is the first view controller that loads when my project runs and I am using an optional variable to populate my tabke vuew that is
'arr'
So when the app runs for the first time its empty . So it might cause a fatal error while using its value in the code. So what is its solution whether to unbind it in the
viewDidLoad()
method or in all total declare an empty NSMutable array type in place of optional type .
Thanks in advance.
I'll start by repeating the my comment from above.
Possibly you've misunderstanding the concept of global variables in Swift.
If you have a global variable, you won't have to "pass" it between any views/methods/classes etc, because the variable is defined at global scope (accessible everywhere).
Generally global variables is not a good idea, and something that you want to avoid.
Regarding the matter of global variables and swift, you really should include singletons into the discussion. See e.g. the following existing SO thread(s):
(How to create a global variable?)
(Declaring Global Variables in Swift)
Communication between TableViewController and ViewController by means of segues (prepare for & unwind segues)
(This answer ended up being very and probably a bit too thorough, as I didn't know in detail what your current tableview/viewcontroller program state looks like. Sorry for the lengthy answer and any inconvenience it might bring to readers of it).
Now, lets leave global variables and discuss one (among other) viable options for the communication between the two controllers in your example. From your question, I'll summarize your example as follows
UITableViewController
consisting ofUITableViewCell
s, where, in these cells, you display some text, say, via instances ofUILabel
.UIViewController
, accessible from the cells of VC1, containing anUITextField
instance. When user enters text into this text field, your want the text to be displayed in the associated cell in VC2 (associated in the sense that it was the cell in VC1 that was used to access VC2).We'll associate VC1 and VC2 with (cocoa touch) classes
TableViewController
(TableViewController.swift) andViewController
(ViewController.swift), respectively. The cells in the table view controller will be associated with (cocoa touch) classTableViewCell
(TableViewCell.swift). Details for these classes follow below.For this simple example, note that we will not embed VC1 into a navigation controller (which is otherwise appropriate for table view -> view navigation).
We'll start in the storyboard, adding objects (drag-and-drop from object library) for a
Table View Controller
and aView Controller
. The table view container will also, automatically, contain, in itsTable View
, aTableViewCell
. Continuing in the storyboard:UILabel
object to theTableViewCell
container in theTable View Controller
(align it as you wish)View Controller
, add aText Field
object and aButton
object (align them as you wish).Table View Controller
.TableViewCell
to theView Controller
.Show
segue and, from the Attributes inspector, enter an identifier for it, say, ShowDetail.TableViewCell
selected, (as above; from the attribute inspector), enter an identifier for the cell. Here, we'll use simply use identifier TableViewCell.We now leave the storyboard for now and implement three classes, associated with the
Table View Controller
, theView Controller
and the formers'TableViewCell
.We start with the
Table View Controller
, and implement ourUITableViewController
sub-class. Note that here, instead of using anNSMutableArray
to hold the texts of theUITextLabel
in each cell, we'll simply use aString
array.Where the two commented out methods are standard methods used in any
UITableViewController
, for number of sections (e.g.return 1
) and cells (e.g.return (numberOfCells ?? 0)
) in the table, respectively. I'll leave fixing these to you.Now, we associate the
TableViewCell
object(s) in the table view with instances of a subclass toUITableViewCell
. Here, we'll use a very simple class for our cells; each cell just containing a singleUILabel
instance (created via storyboard Ctrl-drag as an@IBOutlet
from theUILabel
in the table view cells).Finally, for the view controller that is accessed from the table view cells: use a single
@IBOutlet
to theUITextField
used for user text input, and handle events in this text field using the pre-existingUITextFieldDelegate
. E.g.:We've also declared a string property (
cellText
) here, that will as act as container for communication between VC1 and VC2.We return to the storyboard and---from the Identity inspector---associate the three storyboard objects (
Table View Controller
,View Controller
,TableViewCell
) with their associated classes that we've just written above.We're now almost at our goal; it only remains to specify how to communicate between the two controllers.
We'll begin with communication from VC1 to VC2. In your comment above, you were on the right track (for this specific solution, anyway) by looking at the
prepareForSegue(...)
method. In the class for theTable View Controller
, we add the following method:Hence, for VC1->VC2 communication, we can (in this example) bring whatever existing text that is currently occupying the
UILabel
in the sender cell (as is specified by the String arrayuserTextLabels
). Look at theviewDidLoad(...)
method in the ViewController.swift to see how this value is passed from VC1 and set as default text in theUITextField
in VC2.Now, for communication VC2->VC1, which was the specific communication direction you were asking about, add another method (programmatically), again to TableViewController.swift:
Here, we define an unwind action that, when triggered, retrieves the
cellText
property of the view controller that was the source of the segue, i.e., in our case, the instance ofViewController
. But how do we trigger this action?Return to the storyboard and the
View Controller
. Note the three little icons in the top of theView Controller
object, more specifically, the right-most of these, namedExit
. Ctrl-drag an action from yourButton
to theExit
icon, and select theunwindToTableView
Action Segue. When you click your button the view controller, the view unwind (exit) and land at theunwindToTableView
method in theTableViewController
.The resulting app should look something like this:
This was way longer than I had expected, but once you get started writing... Anyway, the method above uses, naturally, no global variables, but make use of references to future (
prepareForSegue
) or historic (unwindToTableView
) views to get (generally from current or historic view) or set (generally in current of future view) values by using these references (to future/historic view).Apple has their own very thorough tutorial on an example app in the tableviewcontroller/viewcontroller context that I would recommend going over. I found it very valuable myself when I started coding Swift.
Start Developing iOS Apps (Swift)