Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Remove Mediator Bug  (Read 11094 times)
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« on: December 08, 2007, 04:41:41 »

Hi Folks,

View.removeMediator() is now responsible for what will be 3 Maintenance releases. Be very careful with your implementation.

The current issue is that when removing the observers that hold references to a given mediator, each observer list is traversed and when a reference is found it the observer is removed from the list with Array.splice(). This causes all the observers from that point on to move back one in the array. Since we are in an iterator driven loop, the next time the iterator is advanced, it actually skips over the one its supposed to be examining, because it moved back by one during the last iteration.

This will cause a release 1.7 of the AS3 reference implementation sometime within the next week.

If you haven't seen it yet, have a look at this bug report:

http://forums.puremvc.org/index.php?topic=145.0

I'll be implementing the fix described as 'Copy the survivors' in my response there. You might want to have a look at implementing this in your ports.

-=Cliff>
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: December 09, 2007, 09:07:09 »

A more elegant solution presented itself:

http://forums.puremvc.org/index.php?topic=145.msg484#msg484

I'll be posting the code in the next day or two, but here's the method:
:
/**
* Remove an <code>IMediator</code> from the <code>View</code>.
*
* @param mediatorName name of the <code>IMediator</code> instance to be removed.
*/
public function removeMediator( mediatorName:String ) : void
{
// Go through the observer list for each notification
// in the observer map and remove all Observers with a
// reference to the Mediator being removed.
for ( var notificationName:String in observerMap ) {
// the observer list for the notification under inspection
var observers:Array = observerMap[ notificationName ];
// First, collect the indices of the observers to be removed
var removalTargets:Array = new Array();
for ( var i:int=0;  i< observers.length; i++ ) {
if ( Observer(observers[i]).compareNotifyContext( retrieveMediator( mediatorName ) ) == true ) {
removalTargets.push(i);
}
}
// now the removalTargets array has an ascending
// list of indices to be removed from the observers array
// so pop them off the array, effectively going from
// highest index value to lowest, and splice each
// from the observers array. since we're going backwards,
// the collapsing of the array elements to fill the spliced
// out element's space does not affect the position of the
// lower numbered indices we've yet to remove
var target:int;
while ( removalTargets.length > 0 )
{
target = removalTargets.pop();
observers.splice(target,1);
}
// Also, when an notification's observer list length falls to
// zero, delete the notification key from the observer map
if ( observers.length == 0 ) {
delete observerMap[ notificationName ];
break;
}
}
// Remove the to the Mediator from the mediator map
delete mediatorMap[ mediatorName ];
}
-=Cliff>
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #2 on: January 14, 2009, 06:26:18 »

Please double check the latest AS3 reference and not the code above to be sure that you're porting the actual method, as it may have changed since this post. I'm not removing this thread because it is still an important method to make sure you have right!
-=Cliff>
Logged
Pages: [1]
Print