Container View - No Outlet Possible - ios

I have a ViewController with a ScrollView in it, which has 2 ContainerViews in it. Now, every ContainerView loads a ViewController.
And in this ViewControllers (SubController from the ContainerViews) its impossible to do Outlets.
I get the little circles at the outlets, so the reference exists, but setting the text of a label for example, always results in the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
I've done the connection 10 times, with all possible names. Restarted xcode multiple times, still not working.
This answer could help: https://stackoverflow.com/a/28479934/2414069
EDIT: (below code is pseudo, everything is in the place it should..)
#IBOutlet weak var pinInfo_name: UILabel!
#IBOutlet weak var pinInfo_address: UITextView!
#IBOutlet weak var pinInfo_comment: UITextView!
self.pinInfo_name.text = defaults.stringForKey("activePin_name")!
self.pinInfo_address.text = defaults.stringForKey("activePin_address")!
self.pinInfo_comment.text = defaults.stringForKey("activePin_comment")!
SOULUTION:
Ok I slept about it, and found my error within 10 minutes: I wanted to change the .text properties from a object I created in another ViewController. I still have no Idea how to do that, buts thats a story for another time.
tl dr
Access right

As the link in your question points out, having multiple view controllers in your storyboard with the same class could cause this. Did you check that:
The child view controllers do not have the same class as each other
The child view controllers do not have the same class as the parent view controller
I made a test project and the I could connect the outlets of the UILabels in the child view controller to their respective UIViewController subclasses without any problem.
Here's my example:

Related

Why are the outlets by default declared as weak?

I looked up this topic on google but have not got an understandable answer yet, the problem is that I know that when two classes are coupled together by instantiating an object in the first class from the second class and declaring another object in the second class from the first class this will cause a retain cycle that should be broken by using the keyword weak or unowned , yet I can not apply this way of thinking on the IBOutlets being declared as weak
for example
class SignUpViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet weak var signUpBttn: UIButton!
}
this is an outlet in my viewController class, why the outlet is declared as weak ? as per what I understand is that to have a retain cycle, the uibutton class should have an object from the viewController class so that the two classes (viewController and uibutton) become coupled together
can anybody clarify what is happening under the hood?
all ui element in a view controller are part of the viewController view. so view is a UIView class and outlets are reference in the viewController to UIView class elements, so if the view is removed form the view hierarchy all cross element should be weak to avoid cross reference. thew eid problem about this is the reference from apple MVC, where a ViewController is a Controller but have a bunch o related code of the view part. all you outlets should be placed in the UIView class of you ViewController.
TLDR - in my opinion it's not a good decision.
A strong reference denotes ownership. The view or view controller is the owner of the views therefore the logical choice should be strong.
However, in most situations this does not really matter because the views are also strongly referenced by their parent in the view hierarchy.
When does it matter? It matters in situations when you are dynamically updating the view hierarchy by removing views/constraints etc. Once you remove a view/constraint from the hierarchy and you don't have a strong reference to it, it will get removed from memory.
Also note that the combination of weak and ! is a bit dangerous because ! denotes a reference that you expect never to be nil.
This can lead to errors, for example:
#IBOutlet weak var constraint: NSLayoutConstraint!
...
constraint.isActive = false // removes constraint from hierarchy, assigns `nil` to constraint
...
constraint.isActive = true // crashes the app
Personally, I always make outlets strong. For any weak references I always use ? and not !.
Note that weak in this case doesn't have anything to do with protection against reference cycles. It was just a personal decision by Xcode developers.
Historically, there might be a connection with UIViewController.viewDidUnload. However, that method is never called since iOS 6.
Apple recommends that an #IBOutlet be declared as strong. Many discussions / articles can be found about this.
If you take a look at this video from Apple's 2015 WWDC, right around the 32:30 mark: https://developer.apple.com/videos/play/wwdc2015/407/
He states:
In general you should make your outlet strong, especially if you are connecting an outlet to a sub view or to a constraint that's not always going to be retained by the view hierarchy. The only time you really need to make an outlet weak is if you have a custom view that references something back up the view hierarchy and in general that's not recommended.

Indexing issues with Xcode 8

For some reason, defined outlets in XCode are not appearing in the right-click menu when I try to associate an object in the view with the outlet. For example:
import UIKit
class EditProfileTableViewController: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet var photoImageView: UIImageView!
#IBOutlet var businessName: UITextField!
#IBOutlet var businessAddress: UITextField!
#IBOutlet var businessHours: UITextField!
#IBOutlet var businessPhoneNumber: UITextField!
#IBOutlet var businessWebsite: UITextField!
...
As seen in the above example, there are many text fields that were defined, but if I try to associate the outlets to the objects in the view, it doesn't even appear in the right click menu here. (The photoImageView outlet was defined about a month ago, but for some reason the new outlets aren't working.)
In fact, the Identity Inspector shows nothing in the Class dropdown menu:
I believe there was some type of hiccup syncing files on Dropbox and something was accidentally deleted, and now I'm not quite sure how to fix this. I've tried:
Cleaning and re-building the project
Removing the project directories from "~/Library/Developer/Xcode/DerivedData" to force Xcode to re-index (and restarted Xcode)
and still nothing. I'd really hate to completely wipe my project and start from scratch, so I'm hoping to be able to get this resolved. I doubt it's anything as far as in the application that's done incorrectly since this worked before, but I'm not 100%.
If I copy my project folder to another location (let's say from DropBox to my Desktop), everything works perfectly fine! Confusing!
Any suggestions would be greatly appreciated.
There are two possible situation out of my head.
Double check that your view controller on storyboard is really connected to your code. Set a break point in viewDidLoad function to validate this.
If the connection is correct, then the cause of this issue could be that your outlet code is somehow disconnected from the elements on your storyboard. To fix this, do right click on your view controller like your second screen shot. In Outlets section, delete all connections by clicking on the little cross sigh in the middle. Then reconnect by ctr drag the element to your outlets in view controllers.

Why does UILabel.text result in “fatal error: unexpectedly found nil while unwrapping an Optional value”?

I've read several answers to this question and have tried all recommendations with no success. I'm fairly new to swift and am building an app with Swift, PHP and MySQL. I'm receiving the error after the user has logged in to the app and the system should be displaying the username via a label using UILabel.text. The error is occurring on setting a value to the UILabel.text variable. My code is included below. I've tried to hardcode values on other pages and am getting this error throughout my project.
import UIKit
class HomeViewController: UITabBarController {
#IBOutlet var usernameLbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// set global variables
let username = (user!["username"] as AnyObject).uppercased
// label values
print(usernameLbl ?? username!)
usernameLbl.text = username
}
}
I'm accessing the HomeViewController programmatically. The app uses a tab bar and the first page of it is Home. The code is from a course I'm taking on Udemy. Here is how I'm accessing Home:
// func to pass to home page or to tabBar
func login() {
// refer to our Main.storyboard
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// store our tabBar Object from Main.storyboard in tabBar var
let tabBar = storyboard.instantiateViewController(withIdentifier: "tabBar")
// present tabBar that is storing in tabBar var
window?.rootViewController = tabBar
}
You might want to follow best practices and avoid the use of ! as much as possible.
The error you've got happens when you try to access a value or reference stored in an optional that does not contain any value (i.e., it is nil).
In your case, if usernameLbl is nil, usernameLbl.text will crash your app (Think "null pointer exception" in Java, perhaps?).
It is very common to define outlests as:
#IBOutlet weak var label: UILabel!
...instead of the safer:
#IBOutlet weak var label: UILabel?
...because the first one allows you to access its properties without using the ? (i.e. label.text vs. label?.text). But there's an implicit assumption that the label is not nil: the ! by itself does nothing to prevent this (it only silences the compiler, telling it "I know what I'm doing, trust me!").
That shouldn't be a problem as long as you only access it after viewDidLoad() and your outlets are proerly connected in Interface Builder/storyboard, because in that case it will be guaranteed to not be nil.
My guess is that you forgot to hook up the outlet to your label.
Here is a tutorial on storyboards in case it helps.
The whole reason outlets need to be defined as optionals (implicitly unwrapped ! or "standard" ?) is that in Swift, all properties must have a value by the time the instance is initialized (actually, even before calling the super class initializer if that applies).
For view controllers, instance initialization happens before the subviews can be initialized and assigned to the properties/outlets. That happens in the method loadView(), which is called lazily (only just before the view is actually needed for display). So by making all subviews optional (and variable, not constant), they can have the temporary "value" of nil by the time the initializer completes execution (thus satisfying Swift's rules).
Edit: If your outlet is still nil at runtime even though it is connected in interface builder, you can at least try to intercept any code resetting it and see what's going on, with a property observer:
#IBOutlet weak var label: UILabel! {
didSet {
if label == nil {
print("Label set to nil!")
// ^ SET A BREAKPOINT IN THIS LINE
}
}
}
Seeing an #IBOutlet on a UITabBarController is very suspicious. You generally have a tab bar controller which presents child UIViewController subclasses, and put labels on those child view controllers, not the tab bar controller. A tab bar controller does not generally have IBOutlet references. The child view controllers would have them.
Double check to which class you've connected that #IBOutlet and confirm whether it's a subclass of UIViewController or UITabBarController.
Think of the ! operator as the "crash if nil" operator. It's actually called the "force unwrap" operator, and is used to "unwrap" an Optional. If the optional contains a nil, it triggers the same error as trying to dereference a null pointer in other languages.
You should avoid the ! operator until you really understand what it does.
IB (Interface Builder) sets up outlets as force-unwrapped so that you can reference them without having to constantly check them for nil. The idea is that your outlets should never be nil, and if they are it's a problem and you WANT to crash. Think of it as a fuse. It triggers an obvious, early failure that's easy to find and fix.
Having a broken outlet (or missing IBAction) is one of the easiest mistakes to make. With an outlet declared as
#IBOutlet var someOutlet: UILabel!
The compiler lets you reference it without unwrapping it, but you will crash if the outlet is nil.
You can avoid the force-unwrap by adding a ? after the outlet name, or using and if let or a guard statement.
However, with outlets, the thing to do is to realize you've got a broken outlet and just fix it. Then your code works fine.
To fix a broken outlet, control-drag from IB to the #IBoutlet declaration in your code. Think of it as hooking up a cable in your entertainment system.
When you declare an outlet in your code the editor puts a little open circle in the margin to the left of the #IBOutlet declaration. When the outlet is connected, the editor shows a filled-in circle, so it's easy to see if an outlet is connected or not. (Same with #IBAction methods.)

In swift, why is UIlabel optional?

Looking at this,
#IBOutlet weak var label1 : UILabel!
Why is UILabel an optional? The fact that I established a IBOutlet connection to that UILabel means that the UILabel DEFINATELY exists, and wouldn't be nil. So why is it an optional UIlabel? and not UILabel?
It's becouse non-optional variables have to be initialized in constructor and leave all lifecicle.
IBOutlets are weak also, what means it can become nil while e.g. view contoller are still alive.
This is about how The View Controller life cycle actually works into play.
Let's be known of Model, View, and Controllers, before proceeding.
The View Controller object itself gets instantiated before the view is loaded i.e. your label. During this time, since view is not even loaded, there is no reference to the label, as it still needs to be created from storyboard.
For this reason, the object becomes nil for a pretty short unnoticable moment. And, when the view is loaded: ViewController, viewDidLoad(), then only the labels reference is assigned to the variable.
This outlines a short description on why optionals are really used in iOS.

Outlet collection in Swift causes Error 254

I'm working on Stanford's Matchismo game and I'm trying to create an array of buttons that I can reference in the controller. it's a card game, each card a button.
I drag/drop a UIButton to the controller and then set it up in an outlet collection. Not only does it set it up but lets me link multiple outlets to that collection. So far so good.
However when I compile my code (target iOS 7.1) I get a 254 error. I've identified that it's the outlet collection that causes the error.
class MainController: UIViewController{
let cardDeck = PlayingCardDeck()
#IBOutlet var cardButtons: UIButton[]
}
When I replace the UIButton[] mention with NSArray the compiler loads without error. But this is not at all what the exercise is all about - I'm expecting Swift to register the outlets that have been linked to the UIButton[] array and allow me to manipulate that array.
That is, as far as I can tell, the expectation set by the "link to outlet collection" feature in XCode6 Beta 3.
I uploaded a screenshot of the error report. Apparently this has to do with unwrapping the weakly referenced optional array. This is beyond my powers to fix on my own.
You need to define it properly, currently your declaration is not proper -
If you are defining outlet of array of buttons then use -
#IBOutlet var cardButtons: Array <UIButton>
If you are defining outlet of single button then use -
#IBOutlet var cardButton: UIButton
This is still not working in Xcode seed 6.3, however for possible workaround check this link - link
Try This
#IBOutlet var cardButtons: Array<UIButton>

Resources