I have very strange behavior in my app, that I can't explain. I have a SceneKit session running, and some nodes have constraints assigned (no matter what kind). When app goes to background I'm removing all nodes from the scene, and when it appears again I'm adding them again (This is needed for reasons not needed here). When I have this constraints assigned and resume app - it crashes. Not always, but very often. I have no idea what to do to fix this. I tried removing constraints when removing nodes, but this did not help. The error I get is in a screenshot. Can someone help me find a solution?
Your question doesn't show the code that you are referencing, but I can tell you that an EXC_BAD_ACCESS error typically means you are trying to access an object that has been released from memory.
Without going in depth about strong vs. weak variables, you likely have a weak or unowned variable (to that constraint) that is becoming nil and that you are trying to access (by force-unwrapping).
When you are removing these nodes, or when the view disappears, the constraint is released from memory. So the fix here is to either make the reference to this constraint strong or to make a new constraint, keep a strong reference to that in the class, and assign that constraint to the object.
Assuming your reference is to a storyboard, replace:
#IBOutlet weak var constraint: NSLayoutConstraint!
With:
#IBOutlet var constraint: NSLayoutConstraint!
Also note that the variable is probable force-unwrapped (NSLayoutConstraint!), which is likely why you are running into the EXC_BAD_ACCESS error. Set your constraint to be a strong variable instead of weak, or better yet, avoid force-unwrapping optionals if possible!
Note: If this doesn't solve your problem, leave a comment after adding more details to your question.
Related
Setting up a UILabel in Swift I can do the following
#IBOutlet var wLabel: UILabel!
or
#IBOutlet var wLabel: UILabel?
Setting the text I can either do
wLabel.text = "..."
or, for the latter do
wLabel?.text = "..." // with a question mark for the optional
Keeping them optional will help for the case when they are unexpectedly nil as it will just skip this call then and go ahead with the code. Having them declared with the ! would crash the app if the label was nil.
Now why would you not make everything optional? The only reason I could think of would be for better performance. Should I stay away from having them optional if my app has a lot of UI elements so them being optional would mean a disadvantage regarding performance? I wasn't able to find any information on this anyhere.
Using ? in your Outlet will make your code untracable
Crashes are very good in some scenarios, because if no crash is there then it becomes super difficult to trace even small error.
Consider the examples of #IBOutlet with !:
#IBOutlet var wLabel: UILabel!
wLabel.isEnabled = true
Just remove the connection of your Outlet label from your storyboard and run the app, your app will crash on wLabel.isEnabled = true. Since you got a crash so you can got to your storyboard see whether the connection is proper or not. In case there is no connect you add it and damn! you solved the problem easily.
Now consider the examples of #IBOutlet with ?:
#IBOutlet var wLabel: UILabel?
wLabel?.isEnabled = true
Do the same thing, just remove the connection of your Outlet label from your storyboard and run the app, your app won't crash at all. You won't be able to know the error, hence making your code a mess and untracable.
Apple guys were very aware of optional thing, they did force unwrapping of #IBOutlet for a reason. And of course there is no performance difference between ! and ?
If you're setting something up as an outlet it's set up as a force unwrapped optional (with exclamation mark !) because Swift requires your classes to have all of their properties initialized when the object is constructed (i.e. init method is called). Outlets are not created during object construction but rather assigned later when the xib or storyboard data is loaded into your component. Force unwrapped optionals are basically a way to say that you guarantee that the property will be initialized after object's init is called and before they're used.
There are no performance gains to using either of these. An Optional? type means that the property can either be nil or have a value. A force unwrapped optional ! means that the property is guaranteed to have a value when it is used. Upholding this is up to the developer and using such property if its value is nil will result in a crash.
This question already has answers here:
What is the difference between a weak reference and an unowned reference?
(7 answers)
Swift. Is the (absolutely) sole specific advantage of unowned over weak, performance?
(4 answers)
Closed 5 years ago.
I am working on Swift and I have little bit confusion on usage of unowned and weak keywords for memory management in Swift.
Can any one help me to understand where to use unowned ?
Thanks in advance!
The most important difference is that unowned variables are very dangerous in Swift.
weak is an optional type, unowned is NOT.
This means that you can create code that uses weak as part of the logic. (think of asynchronous actions that take place only if a view controller is still being shown on the screen, when the code is ran, if the reference is "weak" it will fail silently without causing any other issues if the code is written correctly)
On the other hand, when a variable is unowned you are basically saying that this variable will always refer to something. And unlike weak, if you call it and there's nothing it will crash.
You generally never wanna use unowned. (I haven't come across any case where I had to). On the other hand, "weak self" variables are quite common when writing blocks.
You can see a good explanation on this question:
Shall we always use [unowned self] inside closure in Swift
EDIT: Actually, check the first and second most voted answers. They provide a clear explanation on WHEN to use unowned and how it works. The second even has pictures!
As per apple docs
There are some pretty good examples given on the developer website, check this link
As far as blocks are concerned as per Apple Docs:
Define a capture in a closure as an unowned reference when the closure
and the instance it captures will always refer to each other, and will
always be deallocated at the same time.
Conversely, define a capture as a weak reference when the captured
reference may become nil at some point in the future. Weak references
are always of an optional type, and automatically become nil when the
instance they reference is deallocated. This enables you to check for
their existence within the closure’s body.
To conclude Use a weak reference whenever it is valid for that
reference to become nil at some point during its lifetime. Conversely,
use an unowned reference when you know that the reference will never
be nil once it has been set during initialization.”
I was facing problem with deallocation of View Controller in my code, then I read about how ARC work and about Strong, Weak and UnOwned references. I was wondering, why swift has made it so complicated? deallocation problem could be solved using slightly different method than what ARC method does. Here is my method:
We can think dependency between objects as directed graph, and can find an unReachable part of graph from current location using proper(using flags) BFS search(in O(n)), and then we can de-initialise all instances which are in unreachable part of graph. Then we can directly work with strong references and there will be no need for weak or unowned references.
Am I missing something here? May be some performance issue or some limitations. Can someone please give me a reason for necessity of Strong, Weak and UnOwned references or some article/document which can explain reason for above in detail?
This is the official documentation and this is a more entertaining discussion. For the most part ARC stays out of your way, just requiring some hints e.g. when creating closures that reference self but execute in the context of another component.
Per:
#IBOutlet weak var nameLabel: UILabel!
Whenever I declare my IBOutlets, i just use var instead of weak var. But I've recently come across a few code templates that use weak var. Why do they do it? What's the added benefit?
Why is there a bang operator at the end of UILabel. I know it's required and i go along w/ it, but just asking it now.
Thanks in advance.
Swift IBOutlet are weak by default (but others properties are strong by default). So both writing are the same.
You have more details about the difference between weak and strong here
According to apple documentation
When you declare an outlet in Swift, you should make the type of the
outlet an implicitly unwrapped optional (!). This way, you can let the
storyboard connect the outlets at runtime, after initialization.
The outlets are weak since the view elements are owned (strongly) by the view. I think it's technically OK for your view controller to have a strong reference too, but not necessary.
Weak variables are optional since they can be nil. You can declare your outlets with ? instead but that means using force-unwrapping or optional binding every time. Declaring them as implicitly-unwrapped optionals with ! is just a convenience.
You use weak when referring to IBOutlets because so long as the object remains in its superview there will be a strong reference to it. See weak or strong for IBOutlets.
Next, the bang operator indicates that the IBOutlet is an explicitly unwrapped label. With the bang operator, it guarantees that the object will exist, so when referencing it, you can simply reference it like this:
someLabel.text = "some text"
However, you can make them IBOutlets optional:
#IBOutlet weak var someLabel: UILabel?
But you must use ? when accessing them
someLabel?.text = "some text"
#gregheo's response is the best explained, to further elaborate: if you consider ownership in this situation the View object referred to by the #IBOutlet usually shouldn't be owned by the View Controller referring to it.
Rather it should be owned by its superview wherever it may be in the tree (which happens strongly by UIView.subviews). The View Controller instead owns the very root of it's View Tree strongly (UIViewController.view). weak explicitly declares a non-owning reference that may become nil at different points in the View Controller's life.
Here I would offer an alternative to using !: using an implicitly unwrapped optional reference is a dangerous practice that weakens the tools Swift offers us. A View Controller which is loaded from Xib or Storyboard includes in its lifetime a regular time after being created and before it's View has been loaded where the #IBOutlet reference is nil, every time. To assume no one will operate on the member during that time means not using the Swift grammar and compiler's feedback to our advantage.
Additionally #IBOutlets are a powerful tool that enables a flexible, visually focused approach when designing a screen or view. It is common practice to have your View Controller expose #IBOutlets for all information it has available, regardless of whether or not it is known that it will be used and separately deciding which to actually connect and use when building and iterating on the View from within Interface Builder.
Additionally-additionally if your View should be flexible enough to be instantiated from Xib/Storyboard AND from code, depending on how you decide referenced subviews should be instantiated and connected they may or may not be available immediately.
For the reasons above I define mine: #IBOutlet weak var nameLabel: UILabel?
I find the following code in UITableView class,
unowned(unsafe) var delegate: UITableViewDelegate?
so I wander how to define a unowned(unsafe) reference delegate for UIView, then I encounter the following error when I write the unowned(unsafe) keyword in my class,
/Users/larryhou/Documents/Xcode/AtomicElements/AtomicElements/AtomicElementView.swift:32:25: 'unowned' cannot be applied to non-class type 'AtomicElementViewDelegate?'
protocol AtomicElementViewDelegate:NSObjectProtocol
{
func didTap(target:AtomicElementView, sender:UITapGestureRecognizer)
}
I can only use weak keyword, but I want keep the reference until UIView is deallocated.
Those two designations - unowned and weak - are equivalent from the perspective of references. Where they differ is the presumption of existence - in Swift, unowned instances are presumed to always exist as long as reference to them does, whereas weak instances are optionals - they may exist, or they may not, so you need to use optional chaining or some other means of working with them.
In UIKit, the delegate pattern with UIView subclasses is to declare them as weak because the delegate is nearly always the view controller that owns the view that the subclass is a subview of. Declaring a delegate as strongly referenced in that situation would set up a reference cycle, hence delegates are typically declared with the weak keyword. If you have a different situation, you can allow your delegate to be strongly referenced by simply leaving out the weak keyword.
In this particular case, unowned (unsafe) is an artifact of being bridged from ObjC.
how to define a unowned(unsafe) reference delegate for UIView
You can't. And you shouldn't want to. unowned(unsafe) is a way of expressing the Objective-C non-ARC assign policy, i.e. no memory management. It is horrible and dangerous (and can cause crashes). The name tells you what the problem is. It is unsafe!!! There is no Swift equivalent because Swift has built-in memory management. This is one of the reasons why Swift is good. Don't worry be happy.
But do be careful, because this designation is warning you that if the delegate goes out of existence while the UITableView still exists, you will crash because the table view will not know this and may try to send a message to the non-existent delegate.