Key-Value-Observing closure never called on Boolean property - swift

I have a class ToolbarManager that inherits from NSObject. It has a toolbar property defined as follows:
#objc dynamic let toolbar: NSToolbar
In the initializer of my class, I call the following code:
init(toolbar: NSToolbar) {
self.toolbar = toolbar
toolbar.allowsUserCustomization = true
observation = observe(\.toolbar.customizationPaletteIsRunning, options: [.old, .new]) {
(_, change) in
print("was running: \(change.oldValue)")
print("is running: \(change.newValue)")
}
}
where observation is another property defined as follows:
var observation: NSKeyValueObservation?
When I run the app and select Customize Toolbar... or close the customization view, the observation closure is never called, and thus nothing is printed to the console.
Why?
(And how can I fix that?)
Edit:
The Apple documentation states:
You can only use key-value observing with classes that inherit from NSObject.
I'm not sure how to understand this. Does it mean that any property defined on NSObject subclasses can be observed or does it mean that only properties that are NSObject subclasses can be tracked?
(The latter would explain why my code doesn't work but then this example which observes a plain Swift string wouldn't work either. And it does work.)

You can only use key-value observing with classes that inherit from NSObject.
means it's required that only objects in a subclass of NSObject can be observed.
It does not mean that any object in a subclass of NSObject is implicitly observable.
It seems that this property of NSToolbar is not KVO compliant.

Related

Swift KVO : how to avoid static?

In my app, I want to use KVO to update UI when an update sent by my server is retrieved by the app. For that, I have a singleton class called "AutomaticRefreshProcess", which polls the server every second, and, if there is a new update, store it in a property lastUpdate. I want this very property to be observable by any object of my app if they need (a UIView, a UIViewController but also maybe by business model NSObject for example)
I saw (at least empirically) that the keyPath when you add an observer couldn't have any of its "node" being a static variable. So I can't do, in my observers :
addObserver(self, forKeyPath:#keyPath(AutomaticRefreshProcess.lastUpdate), options: [.new], context: nil)
I tried, this make the app crash. What I can do is, for all my observers, declare a property set at init to AutomaticRefreshProcess.lastUpdate. I tried, it works.
class MyObserver : NSObject {
#objc dynamic let lastUpdate = AutomaticRefreshProcess.lastUpdate
init()
{
addObserver(self, #keyPath(lastUpdate), ...)
}
}
This works well but, I find it redundant. Plus, I want to customize observeValue raw function to override it by a convenient more specific function to handle these updates, like :
override observeUpdate(newUpdates:[Update], ofType: UpdateType) { ... }
For that, I can create a class ARPObserver, and subclassing all the observers from it. The thing is, how can I make all the UIKit object "conforming" to this parent class, at once ? I don't want to rewrite every UIKit object to make it "ARPOberser" like UIViewARPObserver, UIViewControllerARPObserver etc.
So my question is : is there a better design pattern than subclassing all UIView, UIViewController, and so on to make all UIKit object as ARP Observers ? I would have loved to use extensions but you can't store props there, and I need to store arpInstance to make it available in the keyPath of addObserver

Is there an equivalent to NS_REQUIRES_SUPER in Swift? [duplicate]

Is there a Swift equivalent to
__attribute((objc_requires_super))
which gives a warning if a method doesn't call it's super method?
Basically, I want to warn (or even better, throw a compiler error) if an overridden method doesn't call its super method.
No, there is no Swift equivalent to __attribute((objc_requires_super)).
The equivalent feature, Swift Attributes, contains no such attribute.
The section of the Swift inheritance documentation where such a feature would be mentioned says only:
When you provide a method, property, or subscript override for a subclass, it is sometimes useful to use the existing superclass implementation as part of your override.
Note that you can prevent overriding functions using final, so you could effectively accomplish what you want by providing empty overridable methods that are called by non-overridable methods:
class AbstractStarship {
var tractorBeamOn = false
final func enableTractorBeam() {
tractorBeamOn = true
println("tractor beam successfully enabled")
tractorBeamDidEnable()
}
func tractorBeamDidEnable() {
// Empty default implementation
}
}
class FancyStarship : AbstractStarship {
var enableDiscoBall = false
override func tractorBeamDidEnable() {
super.tractorBeamDidEnable() // this line is irrelevant
enableDiscoBall = true
}
}
Subclasses would then override the overridable methods, and it wouldn't matter whether they called super or not since the superclass's implementation is empty.
As Bryan Chen notes in the comments, this breaks down if the subclass is subclassed.
I make no claims to whether this approach is stylistically good, but it is certainly possible.

Swift class ivars - instantiation time

Lets say you have a class.
class SomeClass: UIViewController {
private var _dataSource = SomeOtherClass()
init() {
// --> breakpoint
super.init(nibName: nil, bundle: nil)
}
}
At the breakpoint in init - I can see that _dataSource is already allocated. At what point is the class actually getting allocated, and when do the class iVars also get init?
Are there some docs on what happens under the hood?
And what's the difference compared to this?
class SomeClass: UIViewController {
private var _dataSource: SomeOtherClass!
init() {
_dataSource = SomeOtherClass()
super.init(nibName: nil, bundle: nil)
}
}
Thanks,
p.s. Coming from Obj-C to Swift world.
In swift, iVar's are assimilated with properties, so I'll be using the term "property" in the rest of the answer.
Property initialization code runs right before running the code of any initializer, as part of a compiler-genarated "initializer". One method to find out about this is by initializing the property from a function, and set a breakpoint inside that function:
class SomeClass: UIViewController {
private var _dataSource = {
// --> breakpoint
return SomeOtherClass()
}()
init() {
// --> breakpoint
super.init(nibName: nil, bundle: nil)
}
}
You should see a stacktrace like this
BTW, in your second code snippet you don't need to declare the property as implicitly unwrapped, as long as you give it a value either inline or within the initializer the compiler will be happy.
The answer to your second question is that, at runtime, there are no differences between assigning the property the value inline (at the declaration site), or within the initializer. There are other advantages/disadvantages with both approaches, at compile time, like with multiple initializers giving a value inline avoids code duplication.
Swift does not expose allocation or bare iVars. Only init methods and properties are exposed.
Do not make assumptions about how allocation is done or how iVars are initialized. The compiler is free to optimize those details in any way it chooses.
Declaration of properties are straight forward.
class SomeClass: UIViewController {
// This is an instance property. It must be set in init(…) before the call to
// super.init(…).
var _dataSource1: SomeOtherClass
// This is an instance property that is set in its declaration. A way to think
// of this is to imagine it being set after allocation and before init(…) is
// called.
var _dataSource2 = SomeOtherClass()
// This is a lazy property. Instead of being set in init(…), lazy properties
// are set when they are first used.
lazy var _dataSource3 = SomeOtherClass()
// This is a class property accessed with SomeClass._dataSource4. All static
// properties are lazy. So, they are set on first use.
static var _dataSource4 = SomeOtherClass()
}
Initialization in Swift is a two-phase process. In the first phase, each property is assigned an initial value. Whereas in Objective-C this meant assigning zeroes and null values, in Swift it also assigns default property values, like here
class SomeClass: UIViewController {
private var _dataSource = SomeOtherClass()
}
Second phase is when initializers are being called. That is why by the time your breakpoint triggers, the default property value for _dataSource has already been assigned.
The difference between
private var _dataSource = SomeOtherClass()
and
private var _dataSource: SomeOtherClass!
is that in the second example you are only declaring a property, which needs to be initialized somewhere further along the road, whereas in the first one you declare it and provide it with a default value.
Note that in the first example, you don't need to explicitly specify the type of the property, because the compiler can infer it from the default value.

Swift property observers, initial value

The Apple documentation states:
The willSet and didSet observers of superclass properties are called when a property is set in a subclass initializer, after the superclass initializer has been called. They are not called while a class is setting its own properties, before the superclass initializer has been called.
which means if I have some type:
enum State {
case disabled, enabled
}
and some variable that has a willSet or didSet observer:
var state: State = .disabled {
willSet {
// do something
}
}
the willSet observer won't get called until after I explicitly set state in during or after initialization of that particular instance.
Why does it work this way? As a developer, I would look at the above code and make the assumption, not unreasonably, that the observer block gets called for the original value, irrespective of instance initialization. It seems like one heck of an anti-pattern to have to set state = .disabled in the initializer to trigger the observer for the initial value.
As Hamish's comment points out, in the case of willSet there's not a valid value that state could have here (and in the case of didSet, there's not a valid value the newValue argument could have).
There's no restriction on whether willSet/didSet can access other properties of the instance. For that reason, all the instance properties need to be properly initialised before any observers are called.
On top of that, if the observer didSet was called when first setting a property's value, the oldValue variable would contain garbage, as it would never have been set.
The way properties are handled in Swift is roughly analogous to the recommended behavior for initialization in Objective-C, notably the section "Don't Use Accessors in Initializer Methods and Dealloc" found on this page. If you set a property foo in your init method, it's equivalent to setting the _foo instance variable in Objective-C, whereas setting foo outside of init is analogous to calling foo's accessors. Basically, what used to be considered a best practice is now actually enforced by the compiler.
The reason for this is to avoid aberrant side effects caused by accessors assuming that the rest of the object's state is set up already, when in actuality it is not.
This can be worked around fairly easily, though; you can make a fooDidSet() method, call that from within foo's didSet, and then also call it at the end of your initializer after calling super's designated init. Alternatively, you can just set the property to itself after calling super's init to cause its didSet to fire.
Think what would happen in a situation like this:
class Person {
var firstName: String {
didSet {
print("New full name:", firstName, lastName)
}
}
var lastName: String {
didSet {
print("New full name:", firstName, lastName)
}
}
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
}
You'd end up using an uninitalized value for lastName. Which can could very well crash the app.
Swift wants to ensure object integrity, and executing observers from init can't guarantee this, as observers have access to all class members.

When should I access properties with self in swift?

In a simple example like this, I can omit self for referencing backgroundLayer because it's unambiguous which backgroundLayer the backgroundColor is set on.
class SpecialView: UIView {
let backgroundLayer = CAShapeLayer()
init() {
backgroundLayer.backgroundColor = UIColor.greenColor().CGColor
}
}
But, just like in Objective-C, we can confuse things by adding local variables (or constants) named similarly. Now the backgroundColor is being set on the non-shape layer:
class SpecialView: UIView {
let backgroundLayer = CAShapeLayer()
init() {
var backgroundLayer = CALayer()
backgroundLayer.backgroundColor = UIColor.greenColor().CGColor
}
}
(this is resolved by using self.backgroundLayer.backgroundColor)
In Objective-C I always eschewed ivars for properties and properties were always prefixed with self for clarity. I don't have to worry about ivars in swift but are there other considerations for when I should use self in swift?
The only times self is required are when referencing a property inside a closure and, as you pointed out, to differentiate it from a local variable with the same name.
However, personally, I prefer to always write "self" because:
That is an instant and obvious sign that the variable is a property. This is important because it being a property means that its state can vary more widely and in different ways than a local variable. Also, changing a property has larger implications than changing a local variable.
The code does not need to be updated if you decide to introduce a parameter or variable with the same name as the property
Code can be easily copied in and out of closures that do require self
Most of the time we can skip self. when we access class properties.
However there is one time when we MUST use it: when we try to set self.property in a closure:
dispatch_async(dispatch_get_main_queue(), {
// we cannot assign to properties of self
self.view = nil
// but can access properties
someFunc(view)
})
one time when we SHOULD use it: so you don't mess a local variable with class property:
class MyClass {
var someVar: String = "class prop"
func setProperty(someVar:String = "method attribute") -> () {
print(self.someVar) // Output: class property
print(someVar) // Output: method attribute
}
}
other places where we CAN use self.
before property just to be expressive about were variable/constant comes from.
Looking at Ray Wenderlich's style guide
Use of Self
For conciseness, avoid using self since Swift does not require it to access an object's properties or invoke its methods.
Use self only when required by the compiler (in #escaping closures, or in initializers to disambiguate properties from arguments). In other words, if it compiles without self then omit it.
Swift documentation makes the same recommendation.
The self Property
Every instance of a type has an implicit property called self, which is exactly equivalent to the instance itself. You use the self property to refer to the current instance within its own instance methods.
The increment() method in the example above could have been written like this:
func increment() {
self.count += 1
}
In practice, you don’t need to write self in your code very often. If you don’t explicitly write self, Swift assumes that you are referring to a property or method of the current instance whenever you use a known property or method name within a method. This assumption is demonstrated by the use of count (rather than self.count) inside the three instance methods for Counter.
The main exception to this rule occurs when a parameter name for an instance method has the same name as a property of that instance. In this situation, the parameter name takes precedence, and it becomes necessary to refer to the property in a more qualified way. You use the self property to distinguish between the parameter name and the property name.
Here, self disambiguates between a method parameter called x and an instance property that is also called x:
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x
}
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
print("This point is to the right of the line where x == 1.0")
}
// Prints "This point is to the right of the line where x == 1.0"
I'm going to go against the flow and not use self unless absolutely required.
The reason why is that two of the main reasons to use self is
When capturing self in a block
When setting self as a delegate
In both cases, self will be captured as a strong reference. This might be what you want, but in many cases, you actually want to use a weak one.
Therefor, forcing the developer to use self as an exception and not a rule will make this strong capture more conscious, and let him reflect on this decision.
As Apple documentation says in https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
The self Property
Every instance of a type has an implicit property called self, which
is exactly equivalent to the instance itself. You use the self
property to refer to the current instance within its own instance
methods.
The increment() method in the example above could have been written
like this:
func increment() {
self.count += 1
}
In practice, you don’t need to write self in your code very often. If
you don’t explicitly write self, Swift assumes that you are referring
to a property or method of the current instance whenever you use a
known property or method name within a method. This assumption is
demonstrated by the use of count (rather than self.count) inside the
three instance methods for Counter.
The main exception to this rule occurs when a parameter name for an
instance method has the same name as a property of that instance. In
this situation, the parameter name takes precedence, and it becomes
necessary to refer to the property in a more qualified way. You use
the self property to distinguish between the parameter name and the
property name.
Here, self disambiguates between a method parameter called x and an
instance property that is also called x:
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x
}
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
print("This point is to the right of the line where x == 1.0")
}
// Prints "This point is to the right of the line where x == 1.0"
Without the self prefix, Swift would assume that both uses of x
referred to the method parameter called x.
I would prefer to keep using self whenever I'm using a property to omit these misunderstandings.
As Nick said, in objective-c we had ivars + synthesized properties which gave the _internal variable names to delineate things. Eg.
#IBOutlet (nonatomic,strong) UITableView *myTableView;
resulting in _myTableView to be (preferably) referenced internally - and self.myTableView to be reference beyond the class. While this is pretty black and white, consider the exception when programmatically instantiating views, you can gain clarity/ simplicity / reduce boilerplate by removing self.
#interface CustomVC:UIViewController
{
UITableView *myTableView;
}
In swift, the public / internal properties clarify this scope.
If it's a public property that other classes will interact with err on self.
Otherwise if it's internal skip self and avoid the automatic repetition.
The compiler will catch you when it's needed.
// UIViewcontroller swift header
public var title: String? // Localized title for use by a parent controller.
public var navigationItem: UINavigationItem { get }
/// In your class
self.title = "Clarity"
self.navigationItem.leftBarButtonItem = UIBarButtonItem()
// In superclass
#property(nonatomic, copy) NSString *screenName // use self.screenName in swift subclass
#IBOutlet myTableView:UITableView // use self
public var myTableView:UITableView // use self
internal var myTableView:UITableView // skip self
var myTableView:UITableView // skip self