Size classes - traitCollectionDidChange crashes with nil value - swift

I have a swift project with a storyboard using Size Classes, a ViewController which conforms to the UITraitEnvironment protocol and have implemented the function traitCollectionDidChange.
When I first launch the app traitCollectionDidChange is called which seems reasonable - it allows developers to handle the first size class presented by the application, however the previousTraitCollection variable passed to it is nil. I can't check that this value is nil as its NOT optional, and accessing it in any way causes a crash. Changing the parameter to optional in the function declaration causes a build error, complaining that I have not implemented required methods in the protocol.
For now I have managed to work around this by creating a separate function which takes an optional variable of the same type that I can then check against, but I would like to know why this is happening.
If its any use to anyone at all, here is the function I am overriding
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection) {
// Accessing previousTraitCollection causes a crash
}
Can anyone shed any light on this?

You have to declare that the type of the argument is optional, because accessing it forces the compiler to try and unpack the address which causes the crash. Replace it with:
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
// Accessing previousTraitCollection causes a crash
}

Related

How do I manually retain in Swift with ARC?

I'm using Swift 3 with ARC in an iOS app, and I want to manually retain an object.
I tried object.retain() but Xcode says that it's unavailable in ARC mode. Is there an alternative way to do this, to tell Xcode I know what I'm doing?
Long Version:
I have a LocationTracker class that registers itself as the delegate of a CLLocationManager. When the user's location changes, it updates a static variable named location. Other parts of my code that need the location access this static variable, without having or needing a reference to the LocationTracker instance.
The problem with this design is that delegates aren't retained, so the LocationTracker is deallocated by the time the CLLocationManager sends a message to it, causing a crash.
I would like to manually increment the refcount of the LocationTracker before setting it as a delegate. The object will never be deallocated anyway, since the location should be monitored as long as the app is running.
I found a workaround, which is to have a static variable 'instance' that keeps a reference to the LocationTracker. I consider this design inelegant, since I'm never going to use the 'instance' variable. Can I get rid of it and explicitly increment the refcount?
This question is not a duplicate, as was claimed, since the other question is about Objective-C, while this one is about Swift.
The solution turned out to be to re-enable retain() and release():
extension NSObjectProtocol {
/// Same as retain(), which the compiler no longer lets us call:
#discardableResult
func retainMe() -> Self {
_ = Unmanaged.passRetained(self)
return self
}
/// Same as autorelease(), which the compiler no longer lets us call.
///
/// This function does an autorelease() rather than release() to give you more flexibility.
#discardableResult
func releaseMe() -> Self {
_ = Unmanaged.passUnretained(self).autorelease()
return self
}
}
This is easily done with withExtendedLifetime(_:_:) function. From the documentation:
Evaluates a closure while ensuring that the given instance is not destroyed before the closure returns.
Cheers!

Swift 2: Why is it necessary to apply ‘as!’ after getting new object by ‘copy()’?

I’ve created new SKEmitterNode object using copy() method. After that i’ve tried to write emitter.position but Xcode said «Ambiguous reference to member ‘position’». But, when i use type conversion «as! SKEmitterNode» after the «copy()», everything is ok. Can you explain me, please, why am i need to use «as!» in this case? I can’t understand this because when i check value type of «emit» variable in debugger, i can see that it’s already have the type SKEmitterNode, even without using «as! SKEmitterNode» after «copy()».
class GameScene: SKScene, SKPhysicsContactDelegate {
let bangEmitter : SKEmitterNode = SKEmitterNode(fileNamed: "MyParticle")!
func makeBang(position: CGPoint) {
// this method causes an error in second line
// but, emit is already have type SKEmitterNode, as debugger says
var emit = bangEmitter.copy()
emit.position = position
// this works ok
var emit = bangEmitter.copy() as! SKEmitterNode
emit.position = position
}
}
Because copy() is a method defined by NSObject and is meant to be overriden by subclasses to provide their own implementation. NSObject itself doesn't support it and will throw an exception if you call copy() on it.
Since it's meant for subclassing, there's no way to tell what the class of the object that will be returned. In Objective-C, it returns an id; in Swift, this becomes AnyObject. Since you, the programmer, know what kind of object you are copying from, you can use as! SomeClass to tell the compiler what kind of object the copy is.
This also speaks to the difference between ObjectiveC and Swift. Objective-C is dynamic. In Objective-C, every time you send a message, the run time will check if the object responds to the message. This happens at run time. In Swift, you call a method and this happens at compile time. The compiler must know the object's type in order to call the right function / method.
This explains why you get emit as an SKEmitterNode in the debugger - this is run time. The compiler doesn't know that at compile time.
Using the as! is an indicator that a check may fail.
Swift 1.2 separates the notions of guaranteed conversion and forced conversion into two distinct operators. Guaranteed conversion is still performed with the as operator, but forced conversion now uses the as! operator. The ! is meant to indicate that the conversion may fail. This way, you know at a glance which conversions may cause the program to crash.
Reference: https://developer.apple.com/swift/blog/?id=23
Look up the definition of the function copy() and you'll see that it always returns Any, therefore you always need to cast it to the object that you're seeking.

Optional properties in swift

If I have property like:
var animatedImagesView:JSAnimatedImagesView?
And eventually it gets initialized at the proper time, do I need to just keep using ! to unwrap it ad nauseum when I want to do something to it? For instance:
self.animatedImagesView!.reloadData()
Usually I unwrap optionals like:
if let dailySleepTime:AnyObject = uw_JSON["daily_sleep_time"] {
self.settings.dailySleepTime = dailySleepTime as String
} else {
log.warning("\n Error finding attr in \(request)\n")
}
but I can't just go around casting my properties to constants in the same way right? I'm not complaining, I'm just wondering if I'm using the exclamation point correctly.
One option is to define animatedImageView as an implicitly unwrapped optional to begin with:
var animatedImagesView: JSAnimatedImagesView!
This is common when dealing with Cocoa .nib objects in Interface Builder, because the View can't be initialized until it is unarchived from the .nib, but you know that it will always be initialized before you use it.
I hate using the ! in general, because it is a runtime error just waiting to happen, but IB objects are one of the few places where its use seems both legitimate and necessary. Otherwise, your two other options are the ones that you have already found - unwrapping it every time using if let... (which is safest, but a pain in the a**), or using the ! every time that you use it, which isn't any safer than just declaring it using ! to begin with.
If you initialize it at the correct time (for example in any of the lifecycle methods, or in the constructor for that matter) you could just use ! instead of ? for the property declaration. I myself usually only use ? for stuff which I dont necessarily know will have a value at all times during my lifecycle.
If the latter is the case for you as well, you need to continue using ? since you can't guarantee you have a value stored. And you should also use the if let myVar = myVar { .. } syntax if you do multiple calls to the variable.
Instead, declare it as follows:
var animatedImagesView:JSAnimatedImagesView!
That implicitly unwrapped optional will obviate the need to constantly "bang" dereference it, but be sure it is never nil at any time accessed.
It's a great way to specify IBOutlets you know will always be initialized from the nib or storyboard before you use them.

Can't unwrap Optional.None when setting window background color

I think I'm missing something very simple here...
override func viewDidLoad() {
self.view.window.backgroundColor = NSColor.grayColor();
}
This returns
fatal error: Can't unwrap Optional.None
which isn't a very descriptive error. Can someone tell me what I'm missing?
Something in the self.view.window.backgroundColor chain (probably self.view.window) is nil. Many view- and view controller-related properties are implemented as implicitly unwrapped, which means that they are Optionals that you can treat like non-Optional variables for convenience's sake. Unfortunately, if you try to access one when it's nil you get the runtime error you're seeing.
Can you set the background color of the view's layer instead? view.window is nil when a view hasn't been added to a window, but view.layer should be there regardless.

Calling method using optional chaining on weak variable causes EXC_BAD_ACCESS

Update: This is fixed in Xcode 6 beta 6.
The following code causes an EXC_BAD_ACCESS on the delegate?.thing() line:
#class_protocol protocol Fooable {
func foo()
}
class Bar : Fooable {
func foo() {
}
}
weak var delegate: Fooable?
let bar = Bar()
delegate = bar
delegate?.foo()
But everything seems right to me. In order for a variable to be weak, it must have optional type. So the variable delegate is optional. A weak variable's type must also be a class type, so I made the protocol a class protocol. Since I use optional chaining, I expect it to either 1) be nil, and do nothing, or 2) not be nil, and call the method, which should succeed. However, it crashes.
Could it be that optional chaining is not atomic and doesn't retain the expression and the object somehow gets deallocated in between the check for nil and the subsequent call?
Interestingly, if you eliminate the variable bar and assign it directly as delegate = Bar(), the crash goes away. This is really perplexing because assigning an expression to a variable and then assigning the variable and assigning the expression directly should generally behave the same.
I suspect the reason weak var delegate: Fooable?is not working is because that line of code, which is using optional chaining, is checking for protocol conformance.
According to Apple Swift Programming manual:
“Even if you are not interoperating with Objective-C, you need to mark
your protocols with the #objc attribute if you want to be able to
check for protocol conformance.”
If you substitute #class_protocol with #objc it should not crash. Also as per the manual, using #objc only allows the protocol to be adopted by classes (no structs or enums conformance).
Like #PartiallyFinite, I had to play with the code a little too. Apple's iBook on Swift has a blurb about this that may help (with a protocol named ExampleProtocol and a class SimpleClass that conforms to that protocol):
"Even though the variable protocolValue has a runtime type of SimpleClass, the compiler treats it as the given type of ExampleProtocol. This means that you can’t accidentally access methods or properties that the class implements in addition to its protocol conformance.”
That said, you should be able to call foo() on your delegate (barring it doesn't go away before calling it), but just remember the delegate here is declared to be of type Fooable?, not Bar, under the hood. This may be a bug, but I got it to work by entering:
weak var delegate: Bar? = bar
delegate?.foo()