# ValueTree hasListener?

**URL:** <https://forum.juce.com/t/valuetree-haslistener/54442>\
**Category:** General JUCE discussion\
**Created:** [January 9, 2023, 8:22am UTC](https://forum.juce.com/t/valuetree-haslistener/54442 "2023-01-09T08:22:32Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![nicolasdanet](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/nicolasdanet/32/56_2.png) [@nicolasdanet](https://forum.juce.com/u/nicolasdanet)\
**Post date:** [January 9, 2023, 8:22am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/1 "2023-01-09T08:22:32Z")

</div>

I’m suprised that ValueTree doesn’t have a `hasListener` method.

Is there something obvious i didn’t see?

---

<div class="post-metadata">

**Author:** ![LiamG](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/liamg/32/6844_2.png) [@LiamG](https://forum.juce.com/u/LiamG)\
**Post date:** [January 9, 2023, 8:58am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/2 "2023-01-09T08:58:54Z")

</div>

It seems to me that the ValueTrees are designed so that you hold the ValueTree as a member variable and then add the listener during construction, and you don’t really need to know whether the same node has any other listeners (at least I’ve never found myself in a position where I needed to know). What’s your use case here?

---

<div class="post-metadata">

**Author:** ![Rincewind](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rincewind/32/10645_2.png) [@Rincewind](https://forum.juce.com/u/Rincewind)\
**Post date:** [January 9, 2023, 9:12am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/3 "2023-01-09T09:12:53Z")

</div>

No much I can add to that - other than that the ListenerList is checking if the listener instance is already added to the list. So if you are in deed adding and removing listeners for some reason (I literally never removed a listener form a value tree), you are protected against having your listener called twice on the same change.

---

<div class="post-metadata">

**Author:** ![nicolasdanet](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/nicolasdanet/32/56_2.png) [@nicolasdanet](https://forum.juce.com/u/nicolasdanet)\
**Post date:** [January 9, 2023, 9:53am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/4 "2023-01-09T09:53:13Z")

</div>

The problem comes from that listeners are not preserved while moving ValueTree.  
In complex case (e.g. a filtering synchronizer) a way to check if a listener has already be binded would have make my initialization process easier.  
For now i rely that duplicate listeners are checked when added/removed.  
But IMHO it would make my code more clear with an explicit check.

---

<div class="post-metadata">

**Author:** ![LiamG](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/liamg/32/6844_2.png) [@LiamG](https://forum.juce.com/u/LiamG)\
**Post date:** [January 9, 2023, 10:00am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/5 "2023-01-09T10:00:39Z")

</div>

Can you wrap your class in a `unique_ptr` and then move that instead? That way the `ValueTree` move constructor wouldn’t get called in the first place.

---

<div class="post-metadata">

**Author:** ![nicolasdanet](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/nicolasdanet/32/56_2.png) [@nicolasdanet](https://forum.juce.com/u/nicolasdanet)\
**Post date:** [January 9, 2023, 10:39am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/6 "2023-01-09T10:39:26Z")

</div>

I guess i could. But add an extra layer of indirection (and memory allocation) is something i would like to avoid at first if not required. But yes it’s a valid approach. 😄

---

<div class="post-metadata">

**Author:** ![LiamG](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/liamg/32/6844_2.png) [@LiamG](https://forum.juce.com/u/LiamG)\
**Post date:** [January 9, 2023, 10:54am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/7 "2023-01-09T10:54:49Z")

</div>

I know that feeling, and I’ve definitely spent lots of time fretting about how much memory allocation is going on in my code. But if it makes you feel any better, moving a `unique_ptr` is just a single pointer swap, whereas moving a stack allocated object can involve a lot more work (as you’ve encountered). So if you’re creating the object infrequently and then moving / swapping it frequently, using `unique_ptr` could possibly be more efficient. Of course I don’t know whether or not this is what is happening in your code, but it’s something to think about.

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [January 9, 2023, 10:57am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/8 "2023-01-09T10:57:41Z")

</div>

> [@Rincewind](#):
>
> (I literally never removed a listener form a value tree)

OT: this is only ok, if the listener is definitely destroyed after the ValueTree, e.g. the ValueTree is a member of the Listener.

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [January 9, 2023, 11:00am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/9 "2023-01-09T11:00:58Z")

</div>

> [@nicolasdanet](#):
>
> I guess i could. But add an extra layer of indirection (and memory allocation) is something i would like to avoid at first if not required.

I agree. I would rather move the object containing the ValueTree around than a heap allocated ValueTree. But that is personal preference, just because I prefer to encapsulate stuff and don’t pass around generic structures.

---

<div class="post-metadata">

**Author:** ![LiamG](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/liamg/32/6844_2.png) [@LiamG](https://forum.juce.com/u/LiamG)\
**Post date:** [January 9, 2023, 11:21am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/10 "2023-01-09T11:21:29Z")

</div>

> [@daniel](#):
>
> OT: this is only ok, if the listener is definitely destroyed after the ValueTree, e.g. the ValueTree is a member of the Listener

Besides ValueTrees as member variables, what other options are there? Either you allocated the ValueTree on the heap (which is a Bad Idea). Or it’s on the stack and about to go out of scope, in which case adding a listener is useless (unless you’re using multiple threads, which is another Bad Idea).

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [January 9, 2023, 11:30am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/11 "2023-01-09T11:30:26Z")

</div>

> [@LiamG](#):
>
> Besides ValueTrees as member variables, what other options are there?

A member variable of a different class:

```auto
struct A
{
    juce::ValueTree tree;
};
struct B : juce::ValueTree::Listener
{
};
A a;
B b;

a.tree.addListener (&b);

```

B can go out of scope and a.tree would call a dangling pointer.  
That’s why ideally B should have a reference to the ValueTree and deregisters itself in it’s destructor.  
Otherwise you need to somehow guard the lifetime of B manually.

---

<div class="post-metadata">

**Author:** ![nicolasdanet](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/nicolasdanet/32/56_2.png) [@nicolasdanet](https://forum.juce.com/u/nicolasdanet)\
**Post date:** [January 9, 2023, 11:39am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/12 "2023-01-09T11:39:19Z")

</div>

And if your app is heavilly based onto ValueTree (as shown in [Dave Rowland’s talk](https://www.youtube.com/watch?v=3IaMjH5lBEY)) there’s design like @daniel example above!

And note that if you std::move the owner of struct A and struct B the binding is removed.

---

<div class="post-metadata">

**Author:** ![LiamG](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/liamg/32/6844_2.png) [@LiamG](https://forum.juce.com/u/LiamG)\
**Post date:** [January 9, 2023, 11:50am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/13 "2023-01-09T11:50:19Z")

</div>

Why not just give B a copy of the ValueTree and let it listen to that?

---

<div class="post-metadata">

**Author:** ![Rincewind](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rincewind/32/10645_2.png) [@Rincewind](https://forum.juce.com/u/Rincewind)\
**Post date:** [January 9, 2023, 11:52am UTC](https://forum.juce.com/t/valuetree-haslistener/54442/14 "2023-01-09T11:52:09Z")

</div>

I’m not so sure about it. Can you maybe supply a better example how you actually run into that pit? My main problem is, that ValueTree listeners are scrubbed when using a std::vector to store them. E.i. one object subscribing to a variable number of value trees with an uncommon parent is not easily possible right now. Only with the unique\_ptr hack.

But I don’t think @Daniel example is in itself very good. He already pointed out, that B should carry his own instance of the value tree it is interested in. I think this is kind of the one main design principle behind the ValueTree and Value. Low cost when copying so every one can get a piece of it and decide what to do when stuff changes.

That of course comes with some challenges. E.g. the execution order of the listeners is often undefined. But I got very comfortable with that and designed my applications in a way, that it doesn’t require a specific order of execution for the listeners.

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [January 9, 2023, 12:03pm UTC](https://forum.juce.com/t/valuetree-haslistener/54442/15 "2023-01-09T12:03:16Z")

</div>

> [@Rincewind](#):
>
> But I don’t think @Daniel example is in itself very good. He already pointed out, that B should carry his own instance of the value tree it is interested in.

I think I didn’t get my point across.

B cannot have an instance of the ValueTree. It could instead have a reference to the ValueTree that keeps the Listeners in order to deregister itself in the destructor.

In any situation where the Listener and the one owning the ListenerList are not somehow related in terms of lifetime, you need to manually make sure a listener is removed before it goes out of scope.

Since you mention vectors, let’s expand:

```auto
struct A
{
    juce::ValueTree tree;
    std::vector<std::unique_ptr<B>> bees;
};

struct B : juce::ValueTree::Listener
{
};

A a;

auto b = std::make_unique<B>();
a.tree.addListener (b.get());
a.bees.pushBack (std::move (b));

a.tree.addChild (...); // is fine
a.bees.clear(); // b is gone, a.tree contains a dangling pointer to the b instance
a.tree.addChild (...); // the listenerList calls a dangling pointer to b

```

It is your obligation to make sure b is removed from the ListenerList.

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [January 9, 2023, 12:04pm UTC](https://forum.juce.com/t/valuetree-haslistener/54442/16 "2023-01-09T12:04:42Z")

</div>

> [@LiamG](#):
>
> Why not just give B a copy of the ValueTree and let it listen to that?

That is indeed what I usually do. The local ValueTree gets the same events like the one it shares the data.

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [January 9, 2023, 12:05pm UTC](https://forum.juce.com/t/valuetree-haslistener/54442/17 "2023-01-09T12:05:11Z")

</div>

> [@nicolasdanet](#):
>
> In complex scenarios (a filtering synchronizer in my case) a way to check if listeners has already be binded would have make initialization process easier.

[You can’t add the same listener multiple times](https://github.com/juce-framework/JUCE/blob/4e68af7fde8a0a64e808fb1a37999a690873c9de/modules/juce_core/containers/juce_ListenerList.h#L94), so if you wanted to ensure a listener is listening to a certain tree you could simply call `addListener()` again.

IMO, it’s bad practice for different listeners to know about each other. Only the listener itself should ever know what it is listening to, and should manage what objects it does or doesn’t listen to itself. For this reason I always make sure to inherit from `Listener` classes privately, and an object’s listener list should always be kept private with the only listener-related methods on its interface being `add`/`remove`.

* * *

Thinking about it a little more, maybe an alternative solution would be to instead expand the interface on the _listener_ to be able to check if it listens to a particular object, e.g.:

```cpp
// Instead of
tree.hasListener (&object);

// Prefer
object.listensTo (tree);

```

This might expose fewer details about the object being observed, and is possibly closer to what you actually want to know in this situation which is whether or not one object is currently observing another.

---

<div class="post-metadata">

**Author:** ![Rincewind](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rincewind/32/10645_2.png) [@Rincewind](https://forum.juce.com/u/Rincewind)\
**Post date:** [January 9, 2023, 12:30pm UTC](https://forum.juce.com/t/valuetree-haslistener/54442/18 "2023-01-09T12:30:33Z")

</div>

I don’t think we get any further in this discussion with using these abstract examples. In my opinion, the examples violates the design principle of the ValueTree in a sense that B should carry his own ValueTree pointing to the same underlying data as you wrote.

My problem with a the ValueTree is that `std::vector<ValueTree>` is not working. And therefore, as a side affect, `std::vector<A>` is also working, if A has a member of a ValueTree.

I’m not saying, that there isn’t one example where one runs into this issues of listener live time, I just can’t think of one, where it would make not only sense in my code but also makes it better either in design or in readability. For me, you (all be it very basic example) exposes multiple issues that makes me avoid that in it’s entirety:

- A is exposing the ValueTree to the public. I use the ValueTree in my objects to store all the data everything I’d normally do with members, so I automatically achieve the observer design pattern with all its benefits. But if I make my ValueTree public, that’s like making all my members public (which I’d normally not do when not using a valuetree) but it’s even worse – now I’m not even sure if my “members” exist or have the type I expect them to have. With the ValueTree, I’m basically getting rid of all strong type guarantees C++ makes. So first thing is I write a wrapper class, that brings that functionality back although behaving the same as a ValueTree (you can add listeners to it and copy it freely around without worrying about live time)
- B is exposing the fact, that it is a ValueTree::Listener. The B instance has no control over the object it is subscribing, the caller can do what every they want with it with no safety measurements what so ever. Even when B would inherit from my wrapper listener (e.g. A::Listener), that ensures all my types etc. are in line, I try as much as possible to make that a private “attribute” of B. There might be some valid use-cases for inheriting a listener class public, but I found that writing the code in a way that there is no need for it, turns out to be better (longer durable, easier to read, easier to test and – if it all goes south – easier to debug).

---

<div class="post-metadata">

**Author:** ![nicolasdanet](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/nicolasdanet/32/56_2.png) [@nicolasdanet](https://forum.juce.com/u/nicolasdanet)\
**Post date:** [January 9, 2023, 2:14pm UTC](https://forum.juce.com/t/valuetree-haslistener/54442/19 "2023-01-09T14:14:07Z")

</div>

> [@Rincewind](#):
>
> I don’t think we get any further in this discussion with using these abstract examples.

 ![Inspector](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/3/3e471bc6248f855f175846891cb73eaeffa2b6b4.png)

I’m not sure you really want to read all the code necessary to illustrate the case. 😆  
Note that it is required for an editable inspector (objects can be changed/deleted at the same time).

> You can’t add the same listener multiple times, so if you wanted to ensure a listener is listening to a certain tree you could simply call `addListener()` again.

By the way that is what i have finally done.

---

<div class="post-metadata">

**Author:** ![Rincewind](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rincewind/32/10645_2.png) [@Rincewind](https://forum.juce.com/u/Rincewind)\
**Post date:** [January 9, 2023, 2:41pm UTC](https://forum.juce.com/t/valuetree-haslistener/54442/20 "2023-01-09T14:41:57Z")

</div>

> [@nicolasdanet](#):
>
> objects can be changed/deleted at the same time

You mean by that, that an object is capable of destroying itself (/remove itself from its parent collection)? Let me just show you how I’m doing it. So the scenario being: we have one collection object (in this case ProgramInlayCollection) and an object being “collected” (that will be ProgramInlay). The ProgramInlay will have attributes (any kind of let’s say “primitive” attributes – `int`s and stuff). So for a possible Inspector component, it just holds a ref to ProgramInlay and can modify by user input and register a ProgramInlay::Listener to it so the inspector component gets updated when the ProgramInlay gets changed from anywhere else in the application. And last but not least, the inspector should present a button “delete” and by that, the ProgramInlay needs to be able to delete itself so the inspector component doesn’t need a ref to ProgramInlayCollection, which would hijack all of our beautiful design work.

So here it goes:

```auto
class ProgramInlay
  : private ValueTree::Listener
{
  public:
    class Listener
    {
      public:
        virtual ~Listener() noexcept = default;
        
        virtual void attachingCtrValChanged(juce::TCtrVal);
        /* and other methods for members */
    };
    
                                              ProgramInlay();
    explicit ProgramInlay(const ValueTree& vt);
                                              ProgramInlay(const ProgramInlay& other);
    
    juce::TCtrVal getAttachingCtrVal() const;
    /* and more getters */
    
    void setAttachingCtrVal(juce::TCtrVal value, UndoManager* undo = nullptr);
    /* and more setters */

    void deleteSelf(UndoManager* undo = nullptr);
    
    void addListener(Listener& listener);
    void removeListener(Listener& listener);
    
  private:
    void valueTreePropertyChanged(ValueTree&, const Identifier& property) override;
    void valueTreePropertyChanged_attachingCtrVal();
    
    
    ValueTree valueTree;
    ListenerList<Listener> listeners;
    
    CachedValue<int> attachingCtrVal;
    /* and more CachedValues for more members */
    
    
    friend class ProgramInlayCollection; // this is necessary, so the collection can mess with the internal valueTree. We take that price, as both classes go and in hand and when we are not exposing anything in ProgramInlayCollection (which we don't), there is no "harm" in doing it.
};

```

And here are the important implementations:

```auto
ProgramInlay::ProgramInlay()
  : ProgramInlay(ValueTree(IDs::PHRASE_PROGRAM_INLAY))
{}

ProgramInlay::ProgramInlay(const ProgramInlay& other)
  : ProgramInlay(other.valueTree)
{}

ProgramInlay::ProgramInlay(const ValueTree& vt)
  : valueTree(vt) /* hook up CachedValues */
{
  jassert(valueTree.hasType(IDs::PHRASE_PROGRAM_INLAY));
  valueTree.addListener(this);
}

void ProgramInlay::valueTreePropertyChanged(ValueTree&, const Identifier& property)
{
  if (property == IDs::attachingNoteNr)
    /* call listeners registered to this node */
  else
    jassertfalse;
}

void ProgramInlay::deleteSelf(UndoManager* undoManager)
{
  jassert(valueTree.getParent().isValid()); // Can't delete an inlay that's not in any collection
  valueTree.getParent().removeChild(valueTree, undoManager);
}

```

And then we also get the collection class:

```auto
class ProgramInlayCollection
  : private ValueTree::Listener
{
  public:
    class Listener
    {
      public:
        virtual ~Listener() noexcept = default;
        
        virtual void inlayAdded(const ProgramInlay& inlay);
        virtual void inlayRemoved(const ProgramInlay& inlay, int index);
        virtual void inlayChanged(const ProgramInlay& inlay); // That is just for convenience and a side product. If we really want to now what goes on, we should subscribe to a ProgramInlay directly.
    };
    
                                              ProgramInlayCollection();
    explicit ProgramInlayCollection(const ValueTree& vt);
                                              ProgramInlayCollection(const ProgramInlayCollection& other);
    
    ProgramInlay createNewInlay(UndoManager* undoManager = nullptr);
    void deleteInlay(const ProgramInlay& inlay, UndoManager* undoManager = nullptr);
    
    void addListener(Listener& listener);
    void removeListener(Listener& listener);
    
  private:
    void valueTreePropertyChanged(ValueTree& vt, const Identifier& property) override;
    void valueTreeChildAdded(ValueTree&, ValueTree& child) override;
    void valueTreeChildRemoved(ValueTree&, ValueTree& child, int ixChild) override;
    
    
    ValueTree valueTree;
    ListenerList<Listener> listeners;
};

ProgramInlayCollection::ProgramInlayCollection()
  : ProgramInlayCollection(ValueTree(IDs::PHRASE_PROGRAM_INLAY_COLLECTION))
{}

ProgramInlayCollection::ProgramInlayCollection(const ProgramInlayCollection& other)
  : ProgramInlayCollection(other.valueTree)
{}

ProgramInlayCollection::ProgramInlayCollection(const ValueTree& vt)
  : valueTree(vt)
{
  jassert(valueTree.hasType(IDs::PHRASE_PROGRAM_INLAY_COLLECTION));
  valueTree.addListener(this);
}

ProgramInlay ProgramInlayCollection::createNewInlay(UndoManager* undoManager)
{
  ProgramInlay inlay;
  valueTree.addChild(inlay.valueTree, valueTree_appendChild /* -1 as index */, undoManager);
  return inlay;
}

// This method is not really needed, as deleting the inlay via its own method doesn't enable that assert to even be possible. This is an example on how the collection is capable of removing elements from itself.
void ProgramInlayCollection::deleteInlay(const ProgramInlay& inlay, UndoManager* undoManager)
{
  jassert(inlay.valueTree.getParent() == valueTree);
  valueTree.removeChild(inlay.valueTree, undoManager);
}

void ProgramInlayCollection::valueTreeChildAdded(ValueTree&, ValueTree& child)
{
  jassert(child.hasType(IDs::PHRASE_PROGRAM_INLAY));
  listeners.call([inlay = ProgramInlay(child)](auto& listener) { listener.inlayAdded(inlay); });
}

void ProgramInlayCollection::valueTreeChildRemoved(ValueTree&, ValueTree& child, int ixChild)
{
  jassert(child.hasType(IDs::PHRASE_PROGRAM_INLAY));
  listeners.call([inlay = ProgramInlay(child), ixChild](auto& listener) { listener.inlayRemoved(inlay, ixChild); });
}

void ProgramInlayCollection::valueTreePropertyChanged(ValueTree& vt, const Identifier& property)
{
  if (vt.hasType(IDs::PHRASE_PROGRAM_INLAY))
    listeners.call([inlay = ProgramInlay(vt)](auto& listener) { listener.inlayChanged(inlay); });
}

```

I also included the three tests, that mark the behaviour that ProgramInlay::deleteSelf is promising:

```auto
- (void) test_deleteSelf
{
  ProgramInlayCollection collection;
  ProgramInlay inlay = collection.createNewInlay();
  
  inlay.deleteSelf();
  XCAssertEqual(collection.indexOfInlay(inlay), -1);
  XCAssertEqual(collection.getNumInlays(), 0);
}

- (void) test_deleteSelf_working_undo
{
  ProgramInlayCollection collection; UndoManager undo;
  ProgramInlay inlay = collection.createNewInlay();
  
  inlay.deleteSelf(&undo);
  undo.undo();
  XCAssertEqual(collection.indexOfInlay(inlay), 0);
  XCAssertEqual(collection.getNumInlays(), 1);
}

- (void) test_deleteSelf_calls_parent_listeners
{
  DECLARE_Spy_Listener_Explicit(ProgramInlayCollection::Listener, inlayRemoved) listener;
  ProgramInlayCollection collection;
  ProgramInlay inlay = collection.createNewInlay();
  
  collection.addListener(listener);
  inlay.deleteSelf();
  XCAssertTrue(listener.__methodWasCalled);
  XCAssertEqual(listener.__param<1>(), 0); // That's prev index of the inlay being removed.
}

```
