I create in the ViewControler a variable with an array of UITextFields like this:
var arrayTextFields = [textField1, textField2, textField3]
I want to use it in the ViewDidLoad or in a function but I can’t.
What do I have to do?
Assuming you have connected the outlets to UITextViews You need to define it within the class declaration and not in any of the methods.
class ViewController: UIViewController {
// Outlets
#IBOutlet var textField1: UITextField!
#IBOutlet var textField2: UITextField!
#IBOutlet var textField3: UITextField!
// define and initialize empty array, can be accessed anywhere within the class
var arrayTextFields: [UITextField] = []
override func viewDidLoad(animated: Bool) {
// set the array in viewDidLoad
arrayTextFields = [textField1, textField2, textField3]
}
}
You have to make sure you connect it to your source file by dragging it from the storyboard while holding "control". then if you follow the code mentioned above, you should have access to do whatever you want.
Related
These are my Outlets, how can I out all off these in an array?
#IBOutlet weak var progressBar1: UIProgressView!
#IBOutlet weak var progressBar2: UIProgressView!
#IBOutlet weak var progressBar3: UIProgressView!
#IBOutlet weak var progressBar4: UIProgressView!
Open the Assistant Editor, right-click and drag from one of your UIProgressView's or just drag from its "Referencing Outlet Collections" to the code file.
Insert outlet collection
Then you can drag from your swift file's #IBOutlet to the rest of your UIProgressView's. Add view to collection
On top declare a variable first like this
var outlets: [UIProgressView] = []
and now on ViewDidLoad method you can use this to put all outlets on that array
like this:
outlets = [progressBar1, progressBar2, progressBar3, progressBar4]
Hope you understand.
class ViewController: UIViewController {
#IBOutlet weak var p1: UIProgressView!
#IBOutlet weak var p2: UIProgressView!
#IBOutlet weak var p3: UIProgressView!
#IBOutlet weak var p4: UIProgressView!
var outlets: [UIProgressView] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
outlets = [
p1,p2,p3,p4
]
}
}
If you have other types of views you can use
var outlets: [UIView] = [...]
As mentioned here Swift - IBOutletCollection equivalent you can use IBOutletCollection to do that. You can drag all your views to one IBOutlet array.
#IBOutlet weak var progressBars: [UIProgressView]!
For example, you can access the first progressBar like
progressBars[0]
But you have to careful about the order of progressBars, when you define IBOutletCollections the collection will not be order guaranteed. You can define the for each view and sort by their tags in runtime as mentioned here also Is IBOutletCollection guaranteed to be of correct order?
To order all views by their tags like
progressBars = progressBars.sorted { $0.tag < $1.tag }
I have a rather complex form designed in the Interface Builder, having about 20 IBOutlets. The form is split onto multiple sections and is static.
Some of the sections might be enabled while the others are disabled (hidden). After the form has been filled in, the app needs to read all of the values (i.e. IBOutlets such as UITextField) and send them to the server.
I used multiple UIStackViews to design each section of the form, so that they could be easily switched on or off.
It's logical after having such a separation with views to have a model that would reflect the same order.
However, I had to link all of the IBOutlets to the UIViewController subclass, flattening any hierarchy.
What I'm trying to achieve is to link individual Form Section Model with specific View. The controller will be responsible only for enabling/disabling the section. The Form Section Model would actually enable specific labels and StackViews and fill in the form values.
Here is the example code I'd like the interface to look like:
import UIKit
class AddressSection {
#IBOutlet weak var sectionStackView: UIStackView!
#IBOutlet weak var sectionTitleLabel: UILabel!
#IBOutlet weak var addressTextField: UITextField!
#IBOutlet weak var isPrimary: UISwitch!
var isHidden: Bool {
get {
return sectionStackView.isHidden
}
set(newValue) {
sectionStackView.isHidden = newValue
}
}
init(){}
}
class NameSection {
#IBOutlet weak var sectionStackView: UIStackView!
#IBOutlet weak var name: UITextField!
#IBOutlet weak var surname: UITextField!
var isHidden: Bool {
get {
return sectionStackView.isHidden
}
set(newValue) {
sectionStackView.isHidden = newValue
}
}
init(){}
}
class MyViewController: UIViewController {
let name = NameSection()
let address = AddressSection()
override func viewDidLoad() {
super.viewDidLoad()
name.isHidden = false
address.isHidden = true
}
}
I have a view that contains labels, and have a button to change the values of the labels. Instead of changing the values one by one in the button, how can I reload the whole view to update the labels.
#IBOutlet weak var one: UILabel!
#IBOutlet weak var two: UILabel!
#IBOutlet weak var three: UILabel!
....
#IBOutlet weak var updateLabels: UIButton!{
//doing something to change the value of the labels
//then wanna reload the whole view
viewDidLoad()
}
I had called the viewDidLoad() method, but didn't work.
You should never call viewDidLoad yourself. It's a framework function that the OS calls, as an indication that your views are ready to be setup.
It would serve better if you separated your function
func updateLabels() {
one.text = "one"
two.text = "two"
three.text = "three"
}
and now you can call the updateLabels function when you want.
Why dont you put all labels on a method. and fire it when ever you need to reload.
override func viewDidLoad() {
super.viewDidLoad()
updateLabels()
}
func updateLabels() {
one.text = "one"
two.text = "two"
three.text = "three"
}
#IBAction func updateLabels(_ sender: Any) {
updateLabels()
}
Your method of updating your labels is incorrect. What you need to do is as follows:
Declare your labels like you did ensuring they are linked in Interface Builder:
//Declare The Labels
#IBOutlet var one: UILabel!
#IBOutlet var two: UILabel!
#IBOutlet var three: UILabel!
Then create an IBAction function which is triggered by a UIButton:
/// Set The Text Labels Text
#IBAction func updateLabelText(){
//Set Label Text
one.text = "one"
two.text = "two"
three.text = "three"
}
Of course remembering to link this to the UIButton instance in Interface Builder.
Hope this helps.
I have a custom class which inherits from UIView inside of which is a UIImageView and button. I'm adding them to my storyboard as UIView and let's say there are two views. I have a delegate and a function which executes when the button is pressed and it works for both UIViews.
My problem is that I don't know how to tell which one was clicked. I need to pass it to another VC and then display suitable image in the UIView which was clicked. I've been thinking of setting ids or something but it does not seem like a very scalable idea.
And I cannot simply add #IBAction because the view is UIView as a whole.
Inside the ViewController I've added them as #IBOutlets:
#IBOutlet weak var view: CustomImageView!
#IBOutlet weak var view2: CustomImageView!
EDIT:
I'm pretty close to creating reusable and scalable solution - I'm just assigning the tag to every object and than passing it and retrieving it. Problem I've encountered is that I would like to access properties of a tag. I didn't find any solution on how to do it.
Solution with delegates
You could add a custom delegate protocol for your custom view
protocol CustomViewDelegate {
func didSelectCustomView(_ view: CustomView)
}
class CustomView: UIView {
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myButton: UIButton!
weak var delegate: CustomViewDelegate?
#IBAction func buttonPressed(sender: UIButton) {
delegate?.didSelectCustomView(self)
}
}
And in your ViewController you have to check from which view to delegate call comes:
class ViewController: UIViewController {
#IBOutlet weak var view1: CustomView!
#IBOutlet weak var view2: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
view1.delegate = self;
view2.delegate = self;
}
}
extension ViewController: CustomViewDelegate {
func didSelectCustomView(_ view: CustomView) {
if view == view1 {
// view1 clicked
} else {
// view2 clicked
}
}
}
Solution with blocks
Instead of a delegate, you could add an optional block that is executed if the button in the view was clicked:
class CustomView: UIView {
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myButton: UIButton!
var clicked: ((CustomView) -> Void)?
#IBAction func buttonPressed(sender: UIButton) {
clicked?(self)
}
}
And in your ViewController, you can add the block to your views:
class ViewController: UIViewController {
#IBOutlet weak var view1: CustomView!
#IBOutlet weak var view2: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
view1.clicked = { view in
}
view2.clicked = { view in
}
}
}
Sorry if this particular problem has been asked about, I followed the answers on other threads but none of them seemed to work, but I just started learning Swift so all of this is pretty new to me.
So, I have a text field in two View Controllers and I want the third View Control to display a result based on the input from the other two controllers when I press a button.
I followed this tutorial and placed the text fields, label and button like I said before.
I placed my code (which you can see below) inside ViewControl.swift.
The problem is that when I attempt to run it I get a "Thread 1 :EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" error in the last two lines.
class ViewController: UIViewController {
var a: String = ""
var b: String = ""
#IBOutlet weak var aTextField: UITextField!
#IBOutlet weak var bTextField: UITextField!
#IBOutlet weak var calculateButton: UIButton!
#IBOutlet weak var resultLabel: UILabel!
#IBAction func calculateButtonPressed(_ sender: UIButton) {
let a = aTextField.text!;
let b = bTextField.text!;
I think that the error is from the data not passing between the views (because before I had everything in the same view and it worked fine), but since I only have one ViewController.swift file I couldn't figure out how to use a Segue.
Do not declare same variables multiple times. Remove let before a & b . You have already declared a & b globally and then tried to redeclare it inside IBAction
class ViewController: UIViewController {
var a: String = ""
var b: String = ""
#IBOutlet weak var aTextField: UITextField!
#IBOutlet weak var bTextField: UITextField!
#IBOutlet weak var calculateButton: UIButton!
#IBOutlet weak var resultLabel: UILabel!
#IBAction func calculateButtonPressed(_ sender: UIButton) {
a = aTextField.text!;
b = bTextField.text!;
Make sure your control outlets are setted properly.
In your two variables a & b are re-declared.Just update your code like below
#IBAction func calculateButtonPressed(_ sender: UIButton) {
self.a = aTextField.text!
self.b = bTextField.text!
}