Latest Posts

Dependency Injection via the Recent "Cake Pattern in Swift" Pattern is Useless in Practice

Dependency Injection means you do not create objects where you use them but “inject” objects a function/method/object depends on from outside. This is a useful trick to make code testable, for example. Once you adopt the mindset, it becomes second nature.

From the Java world stems the imperative to program against interfaces, not implementations. In Swift, this means to define injected dependencies not as concrete types but as protocols.

In an ongoing object collaboration, you will want to store the dependency as a property. The storage of the dependency is up to the component itself. Now the, let’s say, “injectability” can be lifted into a protocol, too. Then you can provide a protocol extension with a default implementation. That’s what Peter-John did in “Dependency Injection with the Cake Pattern” value.

The problem with this approach is that it has 0 real world value and is totally misleading because with that code you will not be able to actually inject anything; you’ll be hiding object creation in a protocol extension only.

Dependency injection is a useful pattern because it allows you to change the concrete object passed in. As I mentioned, apart from the final object in your production code, tests will benefit from injections a lot. When you do not write tests and never pass in another object in production code, you do not need dependency injection. “But it makes my code cleaner!”, people arguing based on principles will say. Yeah sure, it reads like cleaner code, but it’s useless code written like useful code in a “clean” manner. Getting rid of that code is more important than sticking the dependency injection label on it.

Look at the sample code from Peter-John. Here is the dependency as a protocol and some default implementation:

protocol ProductsRepository {
    func fetchProducts() -> [Product]

struct ProductsRepositoryImplementation: ProductsRepository {
    func fetchProducts() -> [Product] { return [] }

And here is the “having a dependency”-protocol, which is the result of what I called “lifting injectability into a protocol”:

protocol ProductsRepositoryInjectable {
    var products : ProductsRepository {get}

extension ProductsRepositoryInjectable {
    var products : ProductsRepository {
        return ProductsRepositoryImplementation()

This protocol with its extension will help you get rid of writing client code like this:

class ClientLong {
    let products: ProductsRepository

    // Inject dependency in initializer:
    init(products: ProductsRepository) {
        self.products = products
    func printPrices() {
        self.products.fetchProducts().forEach {
            print("This \($ costs R\($0.price)")

Instead you can start with a shorter implementation of ProductsRepositoryInjectable:

class ClientShort: ProductsRepositoryInjectable {
    func printPrices() {
        self.products.fetchProducts().forEach {
            print("This \($ costs R\($0.price)")


 This Adidas Sneakers costs R2030.0
 This Nike Sneakers costs R1000.0

There you have it: less code, using cleverly conceived protocols.

There are two very obvious problems:

  • Computed properties don’t work well for non-trivial object creation, for example if setting up the dependency in turn depends on some other dependency; you will want to store the objects. So a *Injectable protocol with a default extension might not always work.
  • No injection, but lots of hand-waving: it doesn’t help a bit when you actually want to reap any benefits of dependency injection, like, injecting a dependency. The code as cited does not allow injection of dependencies. It only hides object creation. To change the dependency in tests, you will need to define a property and override it somehow, via initializer injection or by making the property mutable internally. In any case, you will end up with code similar to ClientLong.

That’s when I concluded that this approach is not going to help you improve your code at all. There has to be more to make it useful in practice. All it does now is shorten the code of a contrived example to impress the reader.

A comment on the original post asked how to use this to inject mocks in tests, and Peter-Johns answer was along the lines of: use a dependency container singleton to create a testing seam. The protocol extension would then return DependencyContainer.instance.productRepository instead of creating a new instance. Actually providing a testing seam is an improvement. It has nothing to do with the pattern, though.

What you will want is code similar to ClientLong to keep the mechanism of injecting dependencies local. Then you use the initializer directly to inject your mock repository: ClientLong(products: mockRepository). You can do this a million times and it will Just Work. But forget to reset a dependency container singleton once and a lot of other tests that use the container will suffer and may even break. It’s also a lot less straightforward to read and understand than the initializer, thus increasing maintenance cost. If you think that accidentally breaking unit tests is a sign of bad tests, you’re right, and writing atomic unit tests for very cohesive objects is an obvious antidote – and now we’ve done a full circle, looking at unit tests for ClientShort which suffer from the very same problem.

A verdict from the author himself in the comment section on Medium is: this is only part 1 to show the basic technique. But, as I argued, it does not show actual dependency injection. It hides object creation in a protocol extension only.

If you take away anything from my post here, it should be that nice-looking samples do not always convey meaningful information, and that slapping “Pattern” onto something does not make it awesome. Or even useful.

Is the Mac mini (Mid 2011) a good developer device in 2017?

Short answer: No.

My trusty Mac mini served me well for years thanks to its 8 GB RAM and the 256 GB SSD. An SSD really helped make it faster back in the day. But with Xcode 9 and macOS 10.13 “High Sierra”, the machine begins to stutter.

I think it’s the CPU not really liking what I demand from it. Xcode 9 builds take a ton longer and the UI is less responsive. Sure, Xcode 9 sports a UI overhaul and might not be as performant as it could be, yet. That doesn’t help with the compile times which, for my current project, now take up to 5mins; that’s not even a fresh build.

So if you want to develop apps with Swift 4 and on the latest macOS, better get a more recent device. I don’t know which to recommend; the MacBook Pro is traditionally a good fit, but an iMac (or upcoming iMac Pro with its uncountable amount of CPUs and endless RAM) might be a good fit, too. Listen to Under the Radar ep. 89 for a more in-depth discussion by Marco Arment and David Smith.

I’d prefer a faster Mac mini because I have a nice-looking screen already and work at my desk 99.99% of the time anyway.

Inject ReSwift Middlewares from Different Project Targets During Runtime

Say you extract the ReSwift-based state module with all your app’s state types, reducers, and middleware into its own framework target. Until you add middlewares to the mix, it’s easy to keep this coherent.

Injecting side-effects through middleware is not easy to do, though, as long as you provide the Store instance from your state module. The store takes an array of Middleware upon initialization. They cannot be changed later. The state module would then depend on your app module with all its network request services and whatnot. That’s the wrong way around, also resulting in a circular dependency. Instead, you have two options to add side-effects that are inherently part of your app’s module, not of the state module:

  1. Create the store inside the app module, not in the state module;
  2. Add a general-purpose side-effect middleware that exposes mutation functions to the outside world.

The latter can look like this:

    .addBeforeReducers { (bananaAction: BananaAction) in 
        Swift.print("Banana action passing through: \(bananaAction)") }

As a bonus (and risk!), this approach allows you to change which middleware are active during runtime. Keep in mind that ReSwift is designed not to allow this, so proceed with caution.

The closure is of type SideEffect. I found it beneficial to not have SideEffect take just any ReSwift.Action by default, because I usually conditionally check for one specific type, not multiple. So I lift the action type filtering to a generic constraint:

public typealias SideEffect<A : Action> = (_ action: A, _ dispatch: DispatchFunction) -> Void

Now you cannot create an array from these function bodies anymore; also, though the Action subtype is now reified as a generic constraint, the actual cast from Action to A has to go somewhere. I put it into a AnySideEffect box:

struct AnySideEffect {
    let boxedSideEffect: (Action, DispatchFunction) -> Void

    init<A: Action>(_ base: @escaping SideEffect<A>) {
        self.boxedSideEffect = { action, dispatch in
            guard let castAction = action as? A else { return }
            base(castAction, dispatch)

Now you can have an [AnySideEffect] array and pass any Action through. Only matching actions will be passed to interested middleware.

Heads up: This closure-based approach can allow removing all registered SideEffect, but not specific instances. For that, instead of a typealias‘d closure I’d use a reference type and check for reference equality (===) to remove/deactivate them.

Update 2017-09-29: I renamed the types a bit, from ApplicationMiddleware to SideEffect, etc.

The Full Implementation

/// - parameter action: The expected action to perform a side effect on.
/// - parameter dispatch: Default dispatch function into the current store.
public typealias SideEffect<A : Action> = (_ action: A, _ dispatch: DispatchFunction) -> Void

struct AnySideEffect {
    let boxedSideEffect: (Action, DispatchFunction) -> Void

    init<A: Action>(_ base: @escaping SideEffect<A>) {
        self.boxedSideEffect = { action, dispatch in
            guard let castAction = action as? A else { return }
            base(castAction, dispatch)

    func process(action: Action, dispatch: DispatchFunction) {
        boxedSideEffect(action, dispatch)

public class SideEffectRegistry {
    public static var instance = SideEffectRegistry()
    private init() { }

    internal fileprivate(set) var sideEffects: [AnySideEffect] = []

    public func addBeforeReducers<A: Action>(sideEffect: @escaping SideEffect<A>) {

    internal func process(action: Action, dispatch: DispatchFunction) {
        sideEffects.forEach { $0.process(action: action, dispatch: dispatch) }

let sideEffectsMiddleware: Middleware<AppState> = { dispatch, getState in
    return { next in
        return { action in
                .process(action: action, dispatch: dispatch)


Show a fat iOS-Style Insertion Point in NSTextView

I have no clue why my previous attempts at customizing drawInsertionPoint(in:color:turnedOn:) always produced visual glitches. I really tried a lot of different ways. But it turns out you don’t have to do that much, really:

class MyTextView: NSTextView {
    var caretSize: CGFloat = 4
    open override func drawInsertionPoint(in rect: NSRect, color: NSColor, turnedOn flag: Bool) {
        var rect = rect
        rect.size.width = caretSize
        super.drawInsertionPoint(in: rect, color: color, turnedOn: flag)

    open override func setNeedsDisplay(_ rect: NSRect, avoidAdditionalLayout flag: Bool) {
        var rect = rect
        rect.size.width += caretSize - 1
        super.setNeedsDisplay(rect, avoidAdditionalLayout: flag)

Adapted to Swift from a Gist by koenbok.

That’s all it takes. Marvelous!

Update: So it turns out that the drawing works just fine in a test project, but I end up with 1px-wide insertion points/carets/I-beams when I click with the mouse or press up/down arrow keys. Left and right work fine. I wonder what’s wrong with this. Isn’t it supposed to be a rather simple customization?

How to Use NSGlyph in Swift

I couldn’t find a simple answer on the web at first, so here’s my take for Googlers.

When you need NSGlyph (which is a UInt32), you probably want to use NSATSTypesetter.insertGlyph(_:atGlyphIndex:characterIndex:) or NSGlyphStorage.insertGlyphs(_:length:forStartingGlyphAt:characterIndex:) which in turn is implemented by NSLayoutManager. But the useful glyph types to use like NSControlGlyph are Ints. How do you get a NSGlyph-pointer from these?

Thankfully, in Swift you can satisfy UnsafePointer<NSGlyph> in two useful ways:

  1. Pass a reference to a mutable variable with the & prefix, like:

     let glyphIndex = ...
     let charIndex = ...
     var glyph = NSGlyph(NSControlGlyph)
     layoutManager.insertGlyphs(&glyph, length: 1, forStartingGlyphAt: glyphIndex, characterIndex: charIndex)
  2. Pass an array of immutable values that is going to be kept alive for long enough, like:

     let glyphIndex = ...
     let charIndex = ...
     layoutManager.insertGlyphs([NSGlyph(NSControlGlyph)], length: 1, forStartingGlyphAt: glyphIndex, characterIndex: charIndex)

Since the exemplary insertGlyphs method call uses a plural-s, it’s pretty straightforward to use an array once you stop worrying about the question “where do I get a pointer from?”

Setting the NSTextView Line Height in a Beautiful Way

In the original post about a cheap way to set the line height in a text view to, say, 150%, the result kind of worked but didn’t look that cool. One issue is that the extra line spacing was exclusively added at the bottom.

With the following solution, you’ll get a proper line height with tastefully aligned insertion point and baseline and all.

The TextKit/Cocoa Text thing we are going to change is the lineFragmentRect. TextKit is immensely powerful, but also complex and not easy to start out working with. To increase any given lineFragmentRect, implement NSLayoutManagerDelegate like this:

class ViewController: NSViewController, NSLayoutManagerDelegate {

    let lineHeightMultiple: CGFloat = 1.6
    let font: NSFont = NSFont.systemFont(ofSize: NSFont.systemFontDefaultSize())
    public func layoutManager(
        _ layoutManager: NSLayoutManager,
        shouldSetLineFragmentRect lineFragmentRect: UnsafeMutablePointer<NSRect>,
        lineFragmentUsedRect: UnsafeMutablePointer<NSRect>,
        baselineOffset: UnsafeMutablePointer<CGFloat>,
        in textContainer: NSTextContainer,
        forGlyphRange glyphRange: NSRange) -> Bool {

        let fontLineHeight = layoutManager.defaultLineHeight(for: font)
        let lineHeight = fontLineHeight * lineHeightMultiple
        let baselineNudge = (lineHeight - fontLineHeight) 
            // The following factor is a result of experimentation:
            * 0.6

        var rect = lineFragmentRect.pointee
        rect.size.height = lineHeight

        var usedRect = lineFragmentUsedRect.pointee
        usedRect.size.height = max(lineHeight, usedRect.size.height) // keep emoji sizes

        lineFragmentRect.pointee = rect
        lineFragmentUsedRect.pointee = usedRect
        baselineOffset.pointee = baselineOffset.pointee + baselineNudge

        return true

Note that this will increase the line height for all lines – except the last trailing newline or the height of the blinking insertion point in an empty document.

When you have an empty text or add a trailing newline character to your text, the insertion point is actually outside the very text container you know and love. NSLayoutManager has a extraLineFragmentRectContainer that takes care of the extraLineFragmentRect – which is used for the last (or only) empty line in a text. You need to increase that to a similar value.

If you have trouble wrapping your head around this concept, think about it this way: a newline character is not actually a glyph. It is not drawn. On top of that, a "\n" does belong to the line it is put on, but then you do not really have a line following after that until you type.

The following string:

The first line\nand the second,\nbut after this, there's no 4th.\n

… will be treated by text editors like:

The first line↩︎
and the second↩︎
but after this, there's no 4th↩︎

… where the last line break is a character of the 3rd line, but renders as:

The first line
and the second,
but after this, there's no 4th.

These 3 lines of text are supposed to illustrate that the trailing newline character is a character of the last line with text in it; if you are in a text editor and put the insertion point after the last \n-newline, you’ll be taken to a 4th line of text that doesn’t exist in the document. It’s merely a user experience thing.

So the layout manager cheats. When there’s a trailing newline character (or empty text), it appends the extraLineFragmentRect. In that rect, your insertion point blinks.

To change the height of the extraLineFragmentRect to suit a larger line height multiple setting, there are two places to intervene:

  1. NSLayoutManager.setExtraLineFragmentRect(_:,usedRect:,textContainer:) itself can be changed to call super with a different line height.
  2. Subclassing NSTypesetter and suggesting a larger rect in every occasion you would call NSLayoutManager.setExtraLineFragmentRect.

I have no clue about NSTypesetter, so the next best thing I can control (and thus suggest you do as well) is overriding setExtraLineFragmentRect.

class LayoutManager: NSLayoutManager {

    var lineHeightMultiple: CGFloat = 1.6

    private var font: NSFont {
        return self.firstTextView?.font ?? NSFont.systemFont(ofSize: NSFont.systemFontSize())

    private var lineHeight: CGFloat {
        let fontLineHeight = self.defaultLineHeight(for: font)
        let lineHeight = fontLineHeight * lineHeightMultiple
        return lineHeight

    // Takes care only of the last empty newline in the text backing
    // store, or totally empty text views.
    override func setExtraLineFragmentRect(
        _ fragmentRect: NSRect, 
        usedRect: NSRect, 
        textContainer container: NSTextContainer) {
        // This is only called when editing, and re-computing the 
        // `lineHeight` isn't that expensive, so I do no caching.
        let lineHeight = self.lineHeight
        var fragmentRect = fragmentRect
        fragmentRect.size.height = lineHeight
        var usedRect = usedRect
        usedRect.size.height = lineHeight

            usedRect: usedRect, 
            textContainer: container)

So you end up with a NSLayoutManagerDelegate and a NSLayoutManager and essentially put similar calculations in two different places. You could argue that since we’re working with a NSLayoutManager subclass now anyway, we could override setLineFragmentRect (note the missing “Extra”), too, and have both settings in one place.

I like to keep the dedicated delegate methods alive as long as I can, though, and find the baseline offset setting very convenient for our purposes.

And that’s about it!

If you never dipped your toe into the intricacies of TextKit, I guess you fell like I did: not happy about the many things you have to know for such a simple effect. “If I have to perform this kind of calculation and conform to that kind of complicated delegate methods to increase the line height,” you might ask, “what will I have to go through to implement really fancy features?” – And I really sympathize with that irritation. There’s so many intricacies to know! After 2 weeks of fighting with TextKit, I now have a better overview but still fail to guess which component does what; we’ll see how deep I have to dive and what I’ll find out in the upcoming weeks and months.

Typewriter Mode: Adding Overscrolling to the Text View

Typewriter modes depend on the feature that you can scroll farther up and down than usual. You need extra whitespace, most of the time in both directions. Let’s start with “overscrolling” to understand what we need.

Apps Without Overscrolling

Regular text views show additional bottom whitespace only until you fill it with text. Take TextEdit, for example. You can start to type at the topmost edge of the text view and the rest of the window is blank.

Plenty of whitespace at the bottom in empty TextEdit documents

But as soon as you hit the visual bottom of the view, you cannot scroll up to get the whitespace back. The enclosing NSScrollView only allows you to scroll until the last line of text comes into view.

TextEdit stops scrolling when the last line becomes visible

When you compose a text, looking at the very bottom of your screen most of the time can feel stupid. That’s why typewriter scrolling became so popular: you can type but the edited line stays visually centered on the screen.

Apps With Overscrolling

Now most apps with typewriter scrolling also have overscrolling. But some, like Byword, don’t allow you to scroll beyond the confines of the document until you activate the typewriter mode.

TextMate is a bit different. It allows you to scroll down as much as you like, up until the last line is at the very top of the view.

TextMate allows you to scroll down until the last line of text is at the top

TextMate doesn’t feature a typewriter mode, which basically is overscrolling + locked insertion point location, though, so you have to adjust the scrolled position for yourself.

Implementing Two-Sided Overscrolling in a NSTextView

To tell the NSScrollView that you want to scroll beyond the confines of the text, you need to tell it that its documentView is larger than it actually is. I found increasing the vertical textContainerInset to work pretty well:

class TopAndBottomOverscrollingTextView: NSTextView {
    func scrollViewDidResize(_ scrollView: NSScrollView) {
        let lineHeight: CGFloat = 14 // compute this instead
        let overscrollInset = scrollView.bounds.height - lineHeight
        textContainerInset = NSSize(width: 0, height: overscrollInset)

Now you have increased the text view’s total size by twice the container height, so you have extra space at the top:

… and at the bottom:

One-Sided Overscrolling

The previous result is a good base to get started implementing a typewriter mode. Without a typewriter mode, overscrolling beyond the top of the document is pretty weird, though. You cannot have a textContainerInset with asymmetric values, so you can only set a vertical inset that affects both edges. But you can move the container around. So you’ll end up doing:

  • Set the inset to 1/2 of what you want,
  • move the container up the same value,
  • so that you end with exactly what you want at the bottom.
class BottomOverscrollingTextView: NSTextView {
    func scrollViewDidResize(_ scrollView: NSScrollView) {
        let lineHeight: CGFloat = 14 // compute this instead
        let offset = (scrollView.bounds.height - lineHeight) / 2
        textContainerInset = NSSize(width: 0, height: offset)
        overscrollY = offset
    var overscrollY: CGFloat = 0

    override var textContainerOrigin: NSPoint {
        return super
            .applying(.init(translationX: 0, y: -overscrollY))

Experimentally, I found this computation to work better:

let offset = floor((scrollView.bounds.height - 14) / 2) - 1

It gets rid of half pixels and then adds a tiny extra offset that’ll help keep the last line in sight when you overscroll. If the last line is obscured even 1 pixel, the scroll view will scroll up to pull it into view.

So the bottom overscrolling works as expected:

If you look closely, you’ll see there’s one extra pixel above the text selection

While the top is clean and looks like usual text views:

Implement scrollViewDidScroll Callback Notification

One thing I skipped so far: the origin of scrollViewDidScroll(_:). You have to sign up for notifications for this kind of event, for example in your view controller:

class ViewController: NSViewController {

    @IBOutlet weak var scrollView: NSScrollView!
    @IBOutlet weak var textView: NSTextView!
    func viewDidLoad() {
        scrollView.contentView.postsBoundsChangedNotifications = true
                selector: #selector(scrollViewDidScroll(_:)), 
                name: .NSViewBoundsDidChange, 
                object: scrollView.contentView)

That’s all you need to get rolling.

Next Steps

This is already some achievement in terms of making text editing more user-friendly because now people don’t have to stare at the bottom of the screen (or window) all the time. Still, without the typewriter scrolling that maintains the extra whitespace even when typing, there’s room for improvement.

Scroll NSScrollView Programmatically Without Showing the Scroller Knobs

I am currently working on a typewriter mode text view. Even though this is a very popular trend for a couple of years, I couldn’t find any open source component for this feature. I assume those who figure this out keep it a secret. If that is the case, it doesn’t make that much sense nowadays anymore since every 3rd note taking app or so has such a feature already.

My naive implementation attempts got better over the past days. But keeping the line the user is typing in at the same position relative to the window all the time involves performing a scroll every now and then. But then the scroller knobs show. I tried to circumvent this for a while now, with subclasses and by overriding private API. Here’s what ended up working:

class TypewriterTextView: NSTextView {
    // ... all the really interesting stuff ...
    func typewriterScroll(to point: NSPoint) {
        self.enclosingScrollView?.contentView.bounds.origin = point

Call typewriterScroll(to:) instead of NSView.scroll(_:) to change the scrolled position without flashing the scroller knobs.

Up until a few minutes ago, I would’ve vowed that I tried this and it didn’t work a few days ago. But it does work. Go figure.

Well, power to the people! Guess I can show you a functional example, soon, with the rest of the component explained.

macOS Storyboard Outlet-Like Connections Between View Controllers

Transitioning from Nibs to Storyboards poses a few challenges. One of them being creating outlets from a parent view controller to a child view controller. There is no such thing.

You could say this is the new idiomatic way to create interfaces, but I don’t quite agree with the consequences. How do you pass data to a view controller 4 levels deep in the hierarchy? It’s not obvious. And there are no “embed” segues like you have them on iOS to obtain references.

Just as I have beef with Segue’s, I don’t want my view controllers to be the central point of control. I want to tell them what to do. Eventually, I guess I’ll have to settle for a programmatic view, but that day is not today.

Turns out that NSViewController now sports a childViewControllers: [NSViewController] property which you can use to query for parent–child-relations.

As usual, my custom NSWindowController subclass also was the façade for the whole view hierarchy, implementing all view-related protocols to forward the display(foo:) commands to the child view controllers. That made the transition from Nib to Storyboard very easy, in fact, since there’s just a single point of change. High locality of change for the win! – If only the outdated child view controller outlets were easy to replace.

The best way I came up with is, upon windowDidLoad, traverse the view controller hierarchy and stop when a good match is found. Since even complex views won’t have hierarchies hundreds of levels deep, this doesn’t even take a noticeable amount of time.

This helper function looks for a match by type in a given view controller’s child collection, recursively:

func firstChildViewController<T: NSViewController>(
    _ parentViewController: NSViewController
    ) -> T? 
    for viewController in parentViewController.childViewControllers {
        if let match = viewController as? T { return match }
        if let subChild: T = firstChildViewController(viewController) { return subChild }

    return nil

Since it’s generic, you just have to specify the desired type to look for so the compiler can figure out what you want:

let bananaVC: BananaViewController 
    = firstChildViewController(jungleViewController)

The only limitation is that this will stop on the first match. If you use the same type of NSViewController subclasses in multiple places, you to check for an additional criterion.

Inside my window controller, I use this function as follows:

class AmazingWindowController: NSWindowController {
    var bananaViewController: BananaViewController!
    var appleViewController: AppleViewController!
    override func windowDidLoad() {
        // ...
    fileprivate func loadChildViewControllers() {
        self.bananaViewController = getChildViewController()
        self.appleViewController = getChildViewController()
    fileprivate func getChildViewController<T: NSViewController>() -> T! {
        let firstViewController = self.window!.contentViewController!
        return firstChildViewController(firstViewController)

Okay, so getChildViewController sounds like we’re back in Java-land. But it’s the best name I could come up with; “load” doesn’t fit since the view controller already is loaded. “Fetch” may work, or “find”. Whatever suits you.

With this in place, I am able to instantiate the child view controller reference properties in a fashion that resembles @IBOutlets closest.

And this, in turn, paves the way to extract the façade functionality from the window controller into another object. Nice!

NSSplitViewItem Vibrancy Is Not Added with Every Initializer

After yesterday’s wrap up of my fix for vibrant table views, I have discovered that NSSplitViewItem has 3 initializer variants since macOS 10.11:

  • init(contentListWithViewController: NSViewController)
  • init(sidebarWithViewController: NSViewController)
  • init(viewController: NSViewController)

The latter will not add vibrancy. Guess who, by accident, discovered his table view to be wrapped in a init(sidebarWithViewController:) call.

I’ll leave the other post up as reference for deactivating vibrancy and dealing with NSTableView text drawing intricacies.

Browse the archive

Subscribe via RSS