Swift events: almost generic, almost solution(s)

man wearing black and white stripe shirt looking at white printer papers on the wall

Fotografie de Startup Stock Photos pe Pexels.com

I have been thinking about a possible better/generic solution for adding multi-cast delegate/event dispatching support to Swift class hierarchies since January, i.e. since more than 6 months ago.

While in my opinion the solution below is still not better than the one I proposed back then, being less type safe unfortunately, I wanted to post it anyway, maybe it could help somebody who cares more than me about avoiding boilerplate code (or until first class event entities would eventually reach us in a following Swift update, who knows.)

Disclaimer: I know (and I already mentioned in that earlier post) that there is already a pretty good generic solution proposed by Greg Read, but I struggled to find something without AnyObject internal checks. Note that applying a type condition like T: AnyObject in his code does work but introduces new issues – try it yourself – as Swift would then not allow the delegates variable definition within the client class anymore even if you’d add a Delegate: class clause too – it really needs a class type, not a protocol type then! (Moreover, of course, his WeakWrapper class can also be changed to a struct and some parts of the code need to be adapted a bit to work with Swift 4, but these are side stories.)

So let’s move back a bit, and try something else:

class EventDispatcher {
    func addHandler(_ newHandler: EventHandler) {
        handlers.append(EventHandlerReference(object: newHandler))
    }
    func removeHandler(_ oldHandler: EventHandler) {
        guard let index = handlers.index(where: { handler in handler.object === oldHandler }) else { return }
        handlers.remove(at: index)
    }
    func raise(_ argument: Any) {
        for handler in handlers {
            handler.object?.handle(argument)
        }
    }
    private var handlers = [EventHandlerReference]()
    private struct EventHandlerReference {
        weak var object: EventHandler?
    }
    deinit {
        print("Dispatcher deinit")
    }
}
protocol EventHandler: class {
    func handle(_ argument: Any)
}

As you can see the idea is to extract adding, removing, and raising events (i.e. managing and calling handler delegates) into a Dispatcher class, to be instanced by each service, therefore without having to duplicate the internal code in the service classes themselves. Similar, somewhat, to Greg’s solution, but in our case the EventHandler protocol is not service-specific anymore.

Of course, the private wrapper class (EventHandlerReference) is needed to actually store weak delegate references so that all objects (clients and services) get properly deinitialized eventually – considering Swift‘s ARC context – similarly to the way we do it in the non-generic version (and to the way Greg does it as well).

The main problem with this approach, however, is that EventHandler protocol must not be generic, i.e. it simply can’t have an Argument associated type or otherwise we couldn’t have a list of handlers stored at the dispatcher level (Swift is not C#!)

The only possible solution I could think of in order to get something running, though, was to define a common protocol for the arguments passed when raising and handling events, or, why not?, just use the most simple existing one: Any!

Services can then raise events through a dispatcher object that they would initialize themselves, and clients could handle them by simply implementing the EventHandler protocol:

class Service {
    init(_ name: String) {
        self.name = name
    }
    var name: String
    var dispatcher = EventDispatcher()
    func doSomething(_ info: String) {
        dispatcher.raise(EventType.somethingWasDone(info: info, source: self))
    }
    enum EventType {
        case somethingWasDone(info: String, source: Service)
    }
    deinit {
        print(name, "deinit")
    }
}
class Client: EventHandler {
    init(_ name: String, subscribingTo service: Service) {
        self.name = name
        self.service = service
        service.dispatcher.addHandler(self)
    }
    var name: String
    var service: Service
    func handle(_ argument: Any) {
        guard let type = argument as? Service.EventType else { return }
        switch (type) {
        case .somethingWasDone(let info, let source):
            print(self.name, "observes that something was done about", info, "on", source.name)
        }
    }
    deinit {
        print(name, "deinit")
    }
}

As you can see, the service class can define a custom enum (or any other type) for specifying the event types that it wants to be able to raise, and clients could handle them using switch statements (or otherwise checking the argument values they receive) in their handler method. However, since Swift enum values can also have supplemental arguments themselves, event related information and/or the source of event (the service instance that raises it) can be easily passed to the handler together with the event type.

But in my opinion, an ugly thing must, unfortunately, be done by the client developer anyway: narrow down the event argument value to the known type (e.g. Service1.EventType). As if this was a (too generic) message bus implementation!

let type = argument as? Service.EventType

This line is the one I don’t like at all, and it’s mostly why I think I’d keep using the January (non-generic) solution, myself; besides being more expressive, it’s way more type safe.

But if you want to use the generic idea in your application or framework, don’t forget to remove all deinitializers from the code first – I’ve added them just to be able to check that we don’t get any unexpected reference cycles formed.

For reference purposes – maybe to determine whether or not you can use it – here is some sample usage code and screen output below:

func run() {
    let service1 = Service("S1")
    let service2 = Service("S2")
    let client1 = Client("C1", subscribingTo: service1)
    let client2 = Client("C2", subscribingTo: service2)
    service1.doSomething("a") // C1 handles somethingWasDone("a") for S1
    service1.dispatcher.addHandler(client2)
    service2.dispatcher.addHandler(client1)
    service2.doSomething("b") // C1 and C2 handle somethingWasDone("b") for S2
    service2.dispatcher.removeHandler(client1)
    service2.doSomething("c") // C2 handles somethingWasDone("c") for S2
}
run()
C1 observes that something was done about a on S1
C2 observes that something was done about b on S2
C1 observes that something was done about b on S2
C2 observes that something was done about c on S2
C2 deinit
C1 deinit
S2 deinit
Dispatcher deinit
S1 deinit
Dispatcher deinit

Finally, I must say that there is yet another – more generic/type safe, but not surely better – solution (which I’ve reached to after reading some good StackOverflow debates on miscellaneous Swift amazing features and… amazing lack of features), requiring client developers to define closure typed variables (lazy if they need access to self from within the code) as event handlers. Personally I don’t like this solution too much either because it needs capturing either unowned self or field values of the current client object in order to avoid ARC traps, but again, maybe it is useful for somebody who does both service and client development within an app, rather than publishing a framework:

class Event<Argument> {
    func addHandler(_ newHandler: EventHandler<Argument>) {
        handlers.append(EventHandlerReference(object: newHandler))
    }
    func removeHandler(_ oldHandler: EventHandler<Argument>) {
        guard let index = handlers.index(where: { handler in handler.object === oldHandler }) else { return }
        handlers.remove(at: index)
    }
    func raise(_ argument: Argument) {
        for handler in handlers {
            handler.object?.function(argument)
        }
    }
    private var handlers = [EventHandlerReference]()
    private struct EventHandlerReference {
        weak var object: EventHandler<Argument>?
    }
    deinit {
        print("Event deinit")
    }
}
class EventHandler<Argument> {
    init(_ function: @escaping (Argument)->Void) {
        self.function = function
    }
    var function: (Argument)->Void
    deinit {
        print("Event handler deinit")
    }
}
class Service {
    init(_ name: String = "default") {
        self.name = name
    }
    var name: String
    func doSomething(_ info: Int) {
        somethingWasDone.raise(info)
    }
    var somethingWasDone = Event<Int>()
    deinit {
        print("Service deinit")
    }
}
class Client {
    init(_ name: String, subscribingTo service: Service) {
        self.name = name
        self.service = service
        service.somethingWasDone.addHandler(somethingWasDoneHandler)
    }
    var name: String
    var service: Service
    lazy var somethingWasDoneHandler = EventHandler<Int> { [name] argument in
         print(name, "observes that something was done about", argument)
    }
    deinit {
        print("Client deinit")
    }
}
func run() {
    let service1 = Service("S1")
    let service2 = Service("S2")
    let client1 = Client("C1", subscribingTo: service1)
    let client2 = Client("C2", subscribingTo: service2)
    service1.doSomething(1)
    service2.somethingWasDone.addHandler(client1.somethingWasDoneHandler)
    service2.doSomething(2)
    service2.somethingWasDone.removeHandler(client1.somethingWasDoneHandler)
    service2.doSomething(3)
}
run()
C1 observes that something was done about 1
C2 observes that something was done about 2
C1 observes that something was done about 2
C2 observes that something was done about 3
Client deinit
Event handler deinit
Client deinit
Event handler deinit
Service deinit
Event deinit
Service deinit
Event deinit
Advertisements
Posted in Swift | Tagged , , , , | Leave a comment

ToolTipService.ShowDuration within a specific WPF view

ToolTipService.ShowDuration attached property isn’t inherited from parent to child elements within the WPF visual tree, and therefore values for this property – to produce runtime effects – must be set on all the elements that have ToolTips for which we’d want to change the display duration (i.e. their placement targets.)

Often this is not easy to do, especially if we use components that have internal elements with tool tips that we don’t have direct access to (other than – maybe periodically? – browsing the visual tree programmatically, of course.)

To solve the issue, however, sometimes we can simply define a different default value for ToolTipService.ShowDuration property in the entire application:

ToolTipService.ShowDurationProperty.OverrideMetadata(
    typeof(DependencyObject), new FrameworkPropertyMetadata(30000)); // 30s

But sometimes we’d want to apply a different show duration value only within a specific view within the app, not everywhere. We’d then need to find a better way to do it, i.e. only for the placement target elements of the tool tips that are opening within that part of the visual tree governed by the root view element.

WPF offers a ToolTip.Opened routed event that should help, but because tool tips are not in the main visual tree, the routed events from their side won’t bubble up that much as we would need, so unfortunately this won’t actually work:

<my:Component ToolTip.Opened="MyComponent_ToolTipOpened">
  ...
</my:Component>

What we can do, though, is to try to register the event handler with a style and an event setter. I’ve tested and this solves the problem for good, indeed! Enjoy:

<my:Component>
  <my:Component.Resources>
    <Style TargetType="ToolTip">
      <EventSetter Event="Opened" Handler="MyComponent_ToolTipOpened"/>
    </Style>
  </my:Component.Resources> 
</my:Component>
private void MyComponent_ToolTipOpened(object sender, RoutedEventArgs e)
{
  var toolTip = e.Source as ToolTip;
  var element = toolTip.PlacementTarget;
  ToolTipService.SetShowDuration(element, 30000); // 30s
}
Posted in WPF | Tagged , , ,

Drag gesture recognizer for iOS development (with initial touch location)

blur casual cellphone close up

Photo by Porapak Apichodilok on Pexels.com

As everybody knows, when using a mouse on a computer a drag operation occurs when the mouse button is pressed, then the device is moved, and eventually the button is released. It’s a continuous and precise operation.

In iOS we have (less precise) touches instead, but sometimes we do want to react to a drag operation similarly, upon beginning, moving, and eventually ending touches.

UIPanGestureRecognizer does a pretty good job to identify such drag operations itself, except that when it reaches its began state, the user has already moved the touch(es) a bit and we don’t know the initial location anymore – there’s no locationInViewWhenTouchesBegan property – while we’d need it to accurately compute coordinate deltas for responding to the drag operation.

(In a way that is expected, because we don’t want the pan operation to begin immediately when the first touch begins – as we are waiting to see if the user wants to actually pan or do something else – but it’s annoying, and not the way NSPanGestureRecognizer works with mouse events in macOS Cocoa development.)

To solve this problem (at least today) we need to specialize the recognizer class ourselves, reading and preserving the location in view when the touches actually begin, and use the specialization instead. Note below how we define an initialLocationInView property for this purpose. (You would need to make the class and property public if you would want to use them outside a framework, though.)

import UIKit.UIGestureRecognizerSubclass

class DraggingPanGestureRecognizer: UIPanGestureRecognizer {
    var locationInViewWhenDraggingStarted: CGPoint!
    override func touchesBegan(_ touches: Set, with event: UIEvent) {
        super.touchesBegan(touches, with: event) 
        locationInViewWhenDragStarted = location(in: view)
    }
}

Finally, here is the client code showing how we can use the new service:

@IBAction func pan(_ recognizer: DraggingPanGestureRecognizer) {
    switch recognizer.state {
    case .began:
        let point = recognizer.locationInViewWhenDraggingStarted
        beginDragging(at: point)
    case .changed:
        let point = recognizer.location(in: recognizer.view)
        continueDragging(to: point)
    ...
    }
}

 

Posted in iOS | Tagged , , , , , , , | Leave a comment

Creating great products requires outstanding functional design

(I’ve recently twitted two examples, but I think it the idea deserves a more general blog post, so here we go.)

It’s not enough to be an outstanding developer to be able to create great software (that sells). You need to also be:

  • good at defining the problem(s) that are to be solved – so that you don’t develop something that’s not needed;
  • good at selecting the correct technical architecture for your code – to ensure everything will eventually work great at runtime;
  • but also exceptional at designing for the real end user – so people get actually in love with your app(s) and are captured under your ecosystem for the long term (and if things go viral you won’t even need to pay for ads to sell your creation at large!)

While for an experienced engineer the first two roles are easier to combine (although not always the best thing to do), in my opinion the third one should better be delegated to somebody else who doesn’t do hands-on development himself or herself.

Because (I think) most people are either technical or functional oriented, and technical persons rarely come up with outstanding functional ideas (like, for example, those features that I’ve recently twitted about.)

Dear developer, you need a partner! Dear functional designer, accept a developer. 🙂

close up of beer glass against colored background

Photo by Pixabay on Pexels.com

Posted in Development | Tagged , , , , , | Leave a comment

Delaying (?) unit testing

close up photography of eyeglasses near crumpled papers

Photo by Steve Johnson on Pexels.com

It happens: even if you have clear functional requirements and good architecture from the beginning of a project, sometimes (and often) the code that you initially wrote to develop a specific feature (or an infrastructural aspect) will end up deeply refactored (or rewritten from scratch), possibly more than once. And you may know this all along!

Don’t worry, everything is absolutely fine: it’s in the developer’s [human] nature!

But – ouch! – what if you have already unit tested the code that is being dramatically refactored? Such tests (together with all hours spent on them) are going straight to trash!

@TDD lovers, sorry, I know this hurts. You may argue that test refactoring shouldn’t be needed at all, or at least it could have been done before even writing the first line of the main service (if we’d only followed all rules – and finished version 1 of our product after competition launched version 3?!). But let’s wake up from dreaming; the world is not perfect: so often we want to change the code from inside out, starting with the core and disregarding tests for that moment (I know, we’re bad); and then tests need to be refactored afterwards, and unfortunately that might be harder than writing brand new ones for the updated sheet later (should that word be with an i?)

@All, now don’t get me wrong, though: unit testing is not bad itself! (It must be good, since everybody’s doing it.) 🙂

Indeed, unit testing is an exceptional tool that tremendously helps developers: it allows us to verify and really improve the quality of our code by simply obliging us to think from the client’s perspective and to prove that our code is doing the right thing for them.

But in my opinion, we shouldn’t be required to do it immediately: for example, when we write code for a new class that is part of a larger architecture, we shouldn’t always continue with writing unit tests for it; instead, I think it’s better to complete the code for an entire bunch of classes that work together, providing a complete functional (or technical) aspect of the system (even when those classes themselves combine into more than a single testable unit), and only then to start unit testing for the pieces. Simply because “breaking” things like refactoring happen all the time, but especially in the meantime.

analogue classic clock clock face

Photo by Pixabay on Pexels.com

Note that the developer should still consider unit testing as eventually mandatory, but delaying it could win time (and money) for him/her, his/her team, and the stakeholders.

What is important, though, is to know when to delay writing unit tests (i.e. when is code likely to be further refactored?) and for how long to delay it without generating more issues than solving (i.e. when is code becoming likely to remain unchanged?)

people woman glass lens

Photo by Public Domain Pictures on Pexels.com

All these are up to you, of course, and the required skills will improve with experience. But the idea is just to not be too rigid about unit testing timing, but only about doing it.

(In some teams, this might require a high level of flexibility: for example, if code reviews are done per commit, the reviewer might ask you to do unit testing right away; the team could discuss this, and – upon consensus – change the flow to accept delayed code reviews as well, e.g. reviewing code at feature level rather than doing it for each work item.)

And if I may, I want to suggest something: to ensure you do not forget about the tests that must be eventually written, you can maintain a simple list of all newly added entities (for which you want to delay unit testing), and periodically check it to see what tests you feel should be finally added, and for which items you should better wait a little longer.

orange and green pen on graphing notepad

Photo by freestocks.org on Pexels.com

Posted in Development | Tagged , , | Leave a comment

Mocking “this”

Let’s assume we have a simple service that is also using an inner service, providing a few operations as follows:

public interface IService
{
    string A();
    string B();
    string C();
}

public class Service : IService
{
    private readonly IInnerService innerService;
    public Service(IInnerService innerService)
    {
        this.innerService = innerService;
    }

    public string A()
    {
        return "A";
    }
    public string B()
    {
        return b();
    }
    public string C()
    {
        return innerService.C();
    }
    private string b()
    {
        return "b";
    }
}

public interface IInnerService
{
    string C();
}

public class InnerService : IInnerService
{
    public string C()
    {
        return "InnerC";
    }
}

To unit test the main service, we would probably do something like this:

  • Define a mock for the inner service interface (IInnerService);
  • Create an instance of the main service class (Service) to test;
  • Define test methods to check the main service’s functionality (of course, in isolation of the inner service’s real implementation):
[TestClass]
public class ServiceUnitTests
{
    private Service service;
    private InnerServiceMock innerServiceMock;

    [TestMethod]
    public void AReturnsA()
    {
        SetupInnerServiceMock();
        SetupService();
        var result = service.A();
        Assert.AreEqual("A", result);
    }
    [TestMethod]
    public void BReturnsB()
    {
        SetupInnerServiceMock();
        SetupService();
        var result = service.B();
        Assert.AreEqual("b", result);
    }
    [TestMethod]
    public void CCallsInnerC()
    {
        SetupInnerServiceMock();
        SetupService();
        var result = service.C();
        Assert.IsTrue(innerServiceMock.WasCCalled);
    }
    [TestMethod]
    public void CReturnsWhatInnerCReturns()
    {
        SetupInnerServiceMock();
        SetupService();
        var result = service.C();
        Assert.AreEqual("MockC", result);
    }

    private void SetupInnerServiceMock()
    {
        innerServiceMock = new InnerServiceMock();
    }
    private void SetupService()
    {
        service = new Service(innerServiceMock);
    }
}

class InnerServiceMock : IInnerService
{
    public bool WasCCalled { get; private set; }
    public string C()
    {
        WasCCalled = true;
        return "MockC";
    }
}

In the example above, we first test that A directly returns what is expected (i.e. “A”). Then we check that B returns what the private method that it internally calls returns (i.e. “b”), because – of course – we want to test the public service interface, not the private methods. Finally we check that method C of the main service class calls the inner service and that it returns whatever that returns (“MockC”, since we use a mock instance).

As you can see, the tests for C are performed in true isolation from the actual InnerService implementation – which is assumed to have its own unit tests – by using a mock. (Of course, we could have used a mock framework, like Moq, instead of a defining a custom class for this purpose, but for now let’s say we want to do it “by hand”.) Now the fun part: what if we want to add one more method to main service implementation: A2, returning whatever A returns (“A”) plus “2”:

public string A()
{
    return A() + "2";
}

How can we unit test this properly? In a sense, A2 is like B, i.e. it calls another method of the service class (although a public one this time, A). We could therefore simply test that A2 returns “A2” string. But thinking a bit more (and looking from a different perspective), we should see it’s not good enough: we might want to ensure that a single unit test would fail if A implementation changes (and not two). And, of course, to not test the same thing – the “A” part of the output string – twice (the first one is in the original A method test, which remains needed). How can we achieve these goals?

One way would be to define an A implementation within the inner service, or extract an (other) inner service with it – like we have for method C – and then call that method both from A and A2 in the main class, and refactor tests accordingly.

This is what I see many developers do in real projects. However, I always felt this is a little too much to do for very little benefit. (Indeed, in real projects it’s not about functions that simply return strings, generating no side effects like in our demo here.)

From my point of view moving A to an inner service seems like an unnecessary or at least a strange thing to do (at least in case our only reason would be to increase testability).

One first possibly better solution could be to redefine the service to use… itself (selfService field below) and then to test accordingly by mocking the service interface as we would do for another (“normal”) inner service:

public class Service : IService
{
    private readonly IInnerService innerService;
    private readonly IService selfService;

    public Service(IInnerService innerService,
                   IService selfService = null)
    {
        this.innerService = innerService;
        this.selfService = selfService ?? this;
    }
    ...
    public string A2()
    {
        return selfService.A() + "2";
    }
}

[TestClass]
public class ServiceUnitTests
{
    private Service service;
    private InnerServiceMock innerServiceMock;
    private ServiceMock serviceMock;
    ...
    [TestMethod]
    public void A2CallsA()
    {
        SetupInnerServiceMock();
        SetupServiceMock();
        SetupService();
        var result = service.A2();
        Assert.IsTrue(serviceMock.WasACalled);
    }
    [TestMethod]
    public void A2ReturnsWhatAReturnsPlus2()
    {
        SetupInnerServiceMock();
        SetupServiceMock();
        SetupService();
        var result = service.A2();
        Assert.AreEqual("MockA" + "2", result);
    }
    ...
    private void SetupServiceMock()
    {
        serviceMock = new ServiceMock();
    }
    private void SetupService()
    {
        service = new Service(innerServiceMock, serviceMock);
    }
}

...
class ServiceMock : IService
{
    public bool WasACalled { get; private set; }
    public string A()
    {
        WasACalled = true;
        return "MockA";
    }
    public string B() { throw new NotImplementedException(); }
    public string C() { throw new NotImplementedException(); }
    public string A2() { throw new NotImplementedException(); }
}

But I don’t like this solution too much, either. I just doesn’t feel like the greatest one. Does anyone else have a better idea?

It seems Moq offers an alternative: we can use a partial mock for the service if we just design our A method to be virtual, i.e. override-able in our mock class (that’s OK most of the times), and then, when testing A2, we can simply setup the mock to return a custom value, while other times it could call the base class instead.

In my opinion, this feels a little awkward too but the solution is a little more elegant. This is the updated service class (restarting from the initial version, without selfService):

public virtual string A()
{
    return "A";
}

And these updates are for the test class:

private Service service;
private Mock innerServiceMock;
private Mock serviceMock;
...
[TestMethod]
public void A2CallsA()
{
    SetupInnerServiceMock();
    SetupServiceMock();
    SetupService();
    var result = service.A2();
    serviceMock.Verify(m => m.A());
}
[TestMethod]
public void A2ReturnsWhatAReturnsPlus2()
{
    SetupInnerServiceMock();
    SetupServiceMock();
    SetupService();
    var result = service.A2();
    Assert.AreEqual("MockA" + "2", result);
}
...
private void SetupServiceMock()
{
    serviceMock = new Mock(innerServiceMock)
                  { CallBase = true };
    serviceMock.Setup(m => m.A()).Returns("MockA");
}
private void SetupService()
{
    service = serviceMock ?? new Service(innerServiceMock);
}

The serviceMock instance above (of type Mock, not a mock of IService interface) is also a Service itself so it can be used in both contexts: as the tested object and as a mock (that the tested object calls for methods not defined with Setup calls to return mock values).

We can learn from this approach and even if we don’t want to use Moq (but to manually create our partial mocks), we can do it with more ease than by self-aggregating, with some help from plain old inheritance (assuming method A remains virtual, though, and that the service class is still not marked as sealed).

Here is the final solution that I managed to obtain. (If you have an even better one, don’t hesitate to join into the discussion, i.e. add a comment below. The same if you just want to let us know which solution you like the most: this one or that with aggregation?)

[TestClass]
public class ServiceUnitTests
{
    private Service service;
    private InnerServiceMock innerServiceMock;
    private ServiceMock serviceMock;
    ...
    [TestMethod]
    public void AReturnsA()
    {
        SetupInnerServiceMock();
        SetupService(); // SetupServiceMock not called here!
        var result = service.A();
        Assert.AreEqual("A", result);
    }
    ...
    [TestMethod]
    public void A2CallsA()
    {
        SetupInnerServiceMock();
        SetupServiceMock();
        SetupService();
        var result = service.A2();
        Assert.IsTrue(serviceMock.WasACalled);
    }
    [TestMethod]
    public void A2ReturnsWhatAReturnsPlus2()
    {
        SetupInnerServiceMock();
        SetupServiceMock();
        SetupService();
        var result = service.A2();
        Assert.AreEqual("MockA" + "2", result);
    }
    ...
    private void SetupServiceMock()
    {
        serviceMock = new ServiceMock(innerServiceMock);
    }
    private void SetupService()
    {
        service = serviceMock ?? new Service(innerServiceMock);
    }
}

...
class ServiceMock : Service
{
    public ServiceMock(IInnerService innerService)
        : base(innerService) { }

    public bool WasACalled { get; private set; }
    public override string A()
    {
        WasACalled = true;
        return "MockA";
    }
}
Posted in .NET, C# | Tagged , , , | Leave a comment

Testing Swift deinit

As you probably know, Swift uses ARC for memory management (presumably to improve performance over classic garbage collection based systems).

That means it is very important that you do use weak (or unowned) references whenever cycles could form. For example, when you implement the multi-delegate pattern to simulate event raising, e.g. to notify observers when things change at your service level:

func addDelegate(_ newDelegate: ServiceDelegate) {
    delegates.append(Delegate(object: newDelegate))
}
private var delegates = [Delegate]()
private struct Delegate {
    weak var object: ServiceDelegate?
}
private func somethingWasDone(_ information: String) {
    for delegate in delegates {
        delegate.object?.somethingWasDone(self, information)
    }
}
deinit {
    print("Deinitializing service")
}

To check that the weak var is doing its job you probably want to run a test for your service’s deinit from time to time (having a Client instance created and then deinitialized, but referencing the service in the meantime and also adding itself as a service delegate there to attempt creating a reference cycle):

func run() {
    let service = Service()
    let client = Client(subscribingTo: service)
    service.doSomething()
    client.doMore()
}
run()

You cannot be happier when you see the magic string (“Deinitializing service”) in the output window if you run the code above in a playground. Moreover, if you temporarily remove the weak keyword and rerun the test, you don’t see the string anymore, which is equally great.

It will be a short term joy, however, because checking the output every time is not a brilliant solution, is it? You surely want to automatize the testing process (at least for the first check.) And you think about writing a unit test for deinit. But (how) can you do it?

Here is a possible solution if you use XCTest framework (as simple as I could get it):

import XCTest
@testable import MyFramework

class Tests {
    ...
    func testDeinit() {
        let _ = Client(subscribingTo: ServiceInstance())
        XCTAssertEqual(ServiceInstance.count, 0)
    }
    class ServiceInstance: Service {
        static var count: Int = 0
        init() {
            ServiceInstance.count += 1
        }
        deinit {
            ServiceInstance.count -= 1
        }
    }
    class Client: ServiceDelegate {
        init(subscribingTo object: ServiceObject) {
            self.object = object
            object.addDelegate(self)
        }
        let object: ScheduleDefinitionObject
        func somethingWasDone(_ object: ScheduleDefinitionObject,
                              _ information: String) { }
}

The idea is to create a ServiceInstance class inheriting from Service, supplementary maintaining a static count of the initialized and not yet deinitialized instance objects, and then create and host a service instance within a Client object (that is set up also as a delegate for the service), eventually checking the reference count after letting both the client and service go away.

As the count is finally zero (assuming that we kept the weak var within service’s Delegate struct) the test passes and we’re safe. Otherwise (such as if we temporarily remove that weak keyword) the test won’t pass and we’d know we have a problem.

Now this is finally something that makes us the happiest developers in the world! 🙂

Note that inheriting from Service class is possible because the @testing attribute of import MyFramework at the top makes classes from MyFramework available in the testing module as if they were defined there, so you can even inherit from them. (This is something that is not written in clear in documentation – there it’s indicated just that classes from the imported framework get available for testing as if they were defined as public – but I’ve tested with inheritance and it works as expected as well!)

Posted in Swift | Tagged , , , , | Leave a comment