Why when I pass data to a UILabel directly in the Second View Controller it turns to be nil? - swift

Why when I pass data to a UILabel directly in the Second View Controller it turns to be nil but when I pass data to a variable first and then apply it to the UILabel everything works fine?
The following code crash the app after segue performed (theResult is nil):
Second View Controller:
#IBOutlet weak var theResult: UILabel!
Main View Controler:
secondVC.theResult.text = “Nice”
But when I create a variable in the Second View Controller, I can pass the data to it easily and then apply it to the UILabel without any problem:
Second View Controller:
var calculation: String?
#IBOutlet weak var theResult: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
theResult.text = calculation
}
Main View Controler:
secondVC.calculation = “Nice”
Why is that?
Note: The UILabel has a default value already when it is created in the Storyboard.
I am almost sure that this is not working but I want to know the reason. Why you can easily change for example the background of the Second View Controller like this:
secondVC.view.backgroundColor = .green
but when you touch the IBOutlets it do not work.

Related

attach several UILabels from storyboard to one IBOutlet

I've 15 Labels in my Storyboard they are just texts, also set from storyboard, What I want to do is to style them, but programitically, Therefore I need to create 15 IBOutlets in my ViewController, I wonder if there is any other way of doing that, without 15 IBOutlets,if it's possible to create 1 IBOutlet and attach all of them to that one? because creating 15 of them is kinda stressing...
You can do this with Outlet Collections instead of an IBOutlet for all the labels you want to group together:
One way to do it is to ctrl+drag from your storyboard to your editor and select outlet collection
This will create #IBOutlet weak var labelCollection: UILabel! in your code
This works fine but then you need to add an additional check for the type when looping:
#IBOutlet weak var labelCollection: UILabel!
func setCustomLayout()
{
for label in labelCollection2.subviews
{
if let label = label as? UILabel
{
// do your custom set up here
}
}
}
What I like to do is to create the specific outlet collection in code first if I way to track the same type like so:
#IBOutlet var labelCollection: [UILabel]!
The I drag from the editor to the storyboard
Then I can work with it as follows
#IBOutlet var labelCollection: [UILabel]!
func setCustomLayout()
{
for label in labelCollection
{
// do your customization here
}
}
Then you can loop through the UIViews inside the IBOutletCollection and do the needful

Enabling access to data and displaying that data on two different types of Views

I am accessing a Realm database to load values in my iOS app. The first one works fine. I have a UIViewController with UITextFields. The big picture is that i:
Define the outlets in the ViewController and connect them to the mainstoryboard UITextFields. There are three fields
I set up an array and load the results of the Realm query from a PersonData.swift data model. Three properties defined in the swift file.
In viewDidLoad I call the function to loadPersonData.
The first thing in the loadPersonData func is to put the realm.objects including three properties into the three fields that are defined by the Outlets at the top of the ViewController.
They load perfectly, are editable, and I can save the values of the data entry from the screen to the Realm database with a Realm modify. I can show you this code if you want to see it.
This is all working fine. Now my problem. My next View is a UITableViewController, with prototype cell, and three UILabels in each single cell row. This code has in the past used an Array for testing and that worked fine to load sample data back to the rows. I want to now read Realm data and scroll up and down with the three fields in each row. Later, when I select one,I will expose in another View all of the properties of that object called Year which is approximately 10 properties or UITextFields that can be edited.
I was told to build a subclass for the protype cell that will be a sub to the UITableViewCell.
class BYMyCell: UITableViewCell {
I put the Outlets for the three UILabels from the prototype cell into the BYMyCell.swift subclass. These outlets are connected to the UILabels defined in the prototype cell.
I saw one suggestion about putting the same outlets in the first businessYearViewController where all the row support functions were located. I was told to add the = nil to these outlets.
#IBOutlet weak var yearLabel: UILabel! = nil
#IBOutlet weak var descriptionLabel: UILabel! = nil
#IBOutlet weak var startingDateLabel: UILabel! = nil
Now when I try to move the Results of the Realm query from the three properties to the three Labels there appears to be nil in all the fields. I can see the data come into my businessYearViewController where I make the query, but I am having trouble putting the data into the Outlets in the BYMyCell.swift data model for exposure on the view/screen.
If I should post my two files, I will try to put them in a response. Thanks for your help. I'm pretty sure this has something to do with my lack of knowledge of processing TableViewController and prototype cell coordination. My rows are simple. One row, three labels. I will also have an add button at the top right corner and the ability to edit the fields in another View for data entry and changes.
Edited one hour later with information. This is my loadBusinessYear func.
func loadBusinessYearData() {
businessYearArray = realm.objects(YrData.self)
print(businessYearArray!.count)
print(businessYearArray?[0])
if businessYearArray!.count > 0 {
yearLabel.text = businessYearArray?[0].year
descriptionLabel.text = businessYearArray?[0].yearType
startingDateLabel.text = businessYearArray?[0].startingDate
} else {
yearLabel.text = "Sample Name"
descriptionLabel.text = "Sample .com"
startingDateLabel.text = "Sample Date"
}
}
The two print statements at the top give you the 1 for the count and the object properties as Optionals.
1
Optional(YrData {
ydID = 0;
year = 2020;
yearType = Business Open;
startingDate = 12/28/2019;
firstWeekEndDate = 01/03/2020;
lastWeekEndDate = 01/03/2021;
firstQtrTotal = 520;
secondQtrTotal = 520;
thirdQtrTotal = 520;
fourthQtrTotal = 520;
leapYearExtraWeek = 40;
yearContains53Weeks = 1;
laborReporting = List<LaborReportData> <0x600000a15290> (
);
expenseAccounting = List<ExpenseAccountData> <0x600000a15440> (
);
})
The data subclass is BYMyCell swift file.
import UIKit
class BYMyCell: UITableViewCell {
#IBOutlet weak var yearLabel: UILabel!
#IBOutlet weak var descriptionLabel: UILabel!
#IBOutlet weak var startingDateLabel: 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
}
}

Fatal error: Unexpectedly found nil while changing Image and Label

I am trying to change a picture and a label programmatically.
Here's the current code setup:
#IBOutlet weak var image: UIImageView!
#IBOutlet weak var label: UILabel!
override func viewDidLoad(){
super.viewDidLoad()
setlabel()
setImage()
}
func setImage(){
self.image.image = UIImage(named: name)
}
func setlabel(){
self.label.text = string
}
But unfortunately, I'm receiving nil for both UI elements, the label and the image. I've doublechecked the connection between my storyboard and the variables- they are set correctly, imho. They are available, since I am calling them outside the viewDidLoad function.
Anyone any suggestion?
Regards
I found the solution. I had 2 views- let's call them A and B.
A contained a button- and the button had 2 functions: Change the view and set the labels/images. Those functions were defined in the Controller of view A.
Since I wanted to change the labels and images of view B, I got the exception.
I had to include another Controller and transfer the functions for setting the images and labels to Controller B. Voila, I could change the images and labels.
Summarized: I had the right connections and the right functions, but in the wrong place.
Thank you all!

swift - How to correctly set up a UITextView

I have a view controller that only has a UITextView in it. I'm having a problem initializing the UITextView with another one that I pass to the view controller.
Here's the code for the view controller:
(The File class has a string variable: name, and UITextView variable: content)
// MARK: Properties
var file: File?
#IBOutlet weak var textViewHome: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
navigationItem.title = file?.name
self.automaticallyAdjustsScrollViewInsets = false
print(file?.content.text)
print(textViewHome.text)
textViewHome = file?.content
print(textViewHome.text)
}
The output of those print statements are:
Optional("hello")
hello
So the textViewHome variable gets set with the correct string but nothing shows up in text view when the app is run. I've seen a lot of questions similar to this but haven't found one where the UITextView.text variable is correct but nothing actually shows up. Thanks for any advice
The main problem is that your view hierarchy (what's is showing on the screen) had textViewHome because it's a subview of viewController.view. When you changed the pointer of textViewHome, the view hierarchy still had the old one because you changes the viewController's pointer and you didn't touch the hierarchy.
Design Improvement: It's better to let the File own a string and not UITextView.
class File{
var name: String
var content: String
}
In your viewController, you will have
textViewHome.text = file?.content //content is a string

how add an object in game view controller?

#IBOutlet var green1: UIImageView!
#IBOutlet var red1: UIImageView!
#IBOutlet var blue1: UIImageView!
#IBAction func red(sender: UIButton) {
green1.hidden = true
red1.hidden = false
blue1.hidden = true
}
I want to add and remove objects when the button is pressed.
At the moment they hide and are visible, but i want to remove them completely form the scene when the button is pressed.
And i want the one that is not hidden to appear.
i tried add child and subview but it didn't work the code is in GameViewController.
If you are showing/hiding frequently, changing hidden property is ok, however if you want to remove completely you need to remove the particular image view from its super view.
ex - green1.removeFromSuperView() and when you need it, you have to add as subview and while adding provide its frame.