NSKeyValueObservation and @objc requirement

I have the following 3 classes in my app:

Class 1.

@IBDesignable final class VerticalCarouselView: UIView {
    @objc var font: UIFont = .systemFont(ofSize: 18, weight: .semibold)
    @IBInspectable var textColor: UIColor = .black
    @objc var textAlignment: NSTextAlignment = .center
    ...
}

Class 2.

@IBDesignable final class CircleView: UIView {
    @IBInspectable var circleForegroundColor: UIColor = .white
    @IBInspectable var circleBackgroundColor: UIColor = .black
    ...
}

Class 3.

@IBDesignable final class FlowerView: UIView {
    @IBInspectable var flowerFillColor: UIColor = .white
    @IBInspectable var flowerBorderColor: UIColor = .black
    @IBInspectable var flowerPetalFillImage: UIImage?
    @IBInspectable var flowerPetalBorderImage: UIImage?
    ...
}

All properties included in the listings above are being observed using NSKeyValueObservation. Everything works great but as soon as I remove @objc from font and textAlignment in VerticalCarouselView shown above, the app crashes with Could not extract a String from KeyPath ... error message.

So my question is, why does the font and the textAlignment properties need @objc while the other ones work without problems?

@IBInspectable implies @objc; it's as mundane as that.

NSKeyValueObserving works by introspecting class instances through the Objective-C runtime. Unfortunately, that means it only works on things exposed to Objective-C. (And in fact, merely using @objc is not sufficient; if you want to be sure that all updates are propagated through KVO, you have to use dynamic as well.)

@IBInspectable implies @objc, all right, that makes sense. :man_facepalming:

You also mentioned that merely using @objc is not sufficient. Is dynamic required even if I don't use Objective-C or KVO? I though @objc implies dynamic. So complex!

@objc means "exposed to Objective-C". dynamic means "the implementation might change at runtime". KVO needs both.

(But if you're not using KVO or other features that depend on replacing a method or property's implementation at run time, you don't need dynamic.)

I see. Thank you for taking time and helping me out, Jordan!

1 Like