[swift-evolution] Three questions about a more "dynamic" Swift for InfoQ

Benjamin Spratling bspratling at mac.com
Mon Sep 26 19:44:56 CDT 2016

> On Sep 26, 2016, at 3:29 PM, sergio via swift-evolution <swift-evolution at swift.org> wrote:
> HI all,
> a debate has recently taken place within the Objective-C/Swift dev community concerning the lack in Swift of something “equivalent” to Objective-C runtime programming. When using Swift exclusively, there seems to be no easy equivalent for Cocoa fundamental design patterns such as the Responder Chain, NSUndoManager, KVC/KVO/Bindings — and in general for code that leverages Objective-C's dynamic features (i.e., runtime programming). 

Generic, block-based undo would be much better in Swift than the old NSUndoManager.  Certainly, “invocation-based” undo is just plain gone in Swift, and not necessary in Obj-C.  I’m toying with a from-scratch new undo manager that dynamically persists a cache of large amounts of data that are filling up RAM.  If you’re interested, maybe I’ll post it on git hub.

Responder Chain
The easy way around Swift’s lack of a “respondsTo" is for a controller to provide a reference to the “next” controller in the chain.  Each controller class optionally conforms to a protocol, and the protocol would have the method the control wants to call.  I have used this extensively, and it works pretty well.  I’ve also discovered that a more “iOS” way of building UIs reduces the levels of disconnection between the Control and the Controller that was present in OS X, eliminating the problem in most cases.

KVO was my favorite way to do things in Obj-C; I even wrote some helper classes to prevent the pesky “you didn’t clean up your observers before dealloc” thing.  (I’m using ARC, quit bothering me with that already!)  Unfortunately, Swift’s init/deinit order made those classes impossible (as far as I can tell), so I ditched all KVO.  In the last year, developing 5 apps in pure Swift, I haven’t needed KVO, but I haven’t been working closely with AV modules, which used KVO as its preferred pattern, so I’m not sure how cumbersome the became.  For the one thing I did use AV- for, there was a closure-based API, and there wasn’t an issue.  So I’m preferring closures.  It would be nice (sigh) to use a more declarative approach.  I’ve recently noticed “ReativeSwift”, but haven’t had time to evaluate if it saves me work.

The one thing I wish I did have in the KVO genre is a callback when a weak var went to nil.  For example, reactively removing items from the UndoManager stack when the controller it references is deinit’d.  The iOS way for doing this is for the controller to own the undo manager 

KVC is inherently unsafe in Obj-C, and Swift is all about the safety.  Really all that’s happened, as best I can tell, is I have to write explicit adapters to create objects.  Making a protocol that implements a init?(json:JSON) method, and storing a reference to the protocol and calling it as needed isn’t that bad.  So my need for KVC has disappeared.  I get that bindings were a little different, but I never got that in to bindings in the first place.  It seemed like a whole lot of guesswork and non-safe “stringly-typed” code.  I much prefer knowing at the call site what my types need to be.  (CoreImage drives me nuts).

So I think in general, I need to see with more compelling use case than the ones listed for warrant the kind of dynamic features you’re talking about.  Part of the benefit of Swift to me is the safety.  Taking the time to write my code in a safer way is a large part of the task of making it safe in the first place, but now, the compiler can catch accidental mistakes.

If anything,  I’d like to be able to dependency-inject data when a controller is unarchived from a .nib, for instance.

-Ben Spratling

More information about the swift-evolution mailing list