Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 1.0/2.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 20.12.2006, 18:02
Ромастый вне форума Посмотреть профиль Отправить личное сообщение для Ромастый Найти все сообщения от Ромастый
  № 1  
Ответить с цитированием
Ромастый
 
Аватар для Ромастый

Регистрация: Jan 2004
Адрес: На чердаке.
Сообщений: 1,112
По умолчанию совместное использование Delegate и EventDispatcher

Все знают, что Delegate.create каждый раз возвращает новый объект. И подписавшись раз на событие таким макаром
Код:
myObject.addEventListener("myEvent", Delegate.create(myOtherObject, myOtherObjectMethod));
Отписаться от него потом весьма проблематично.

Можно отписаться от него в самом методе в момент вызова через arguments.caller (с) NoxNoctis

А если надо извне, в любой другой момент?
Вот, тут подумалось, что можно просто обойти цепочку:
Код:
class DelegateRemover {
	public static function removeDelegate(dispatcher, event, obj, func) {
		var queue = dispatcher["__q_"+event];
		var l:Number = queue.length;
		var i:Number;
		for (i=0; i<l; i++) {
			var o = queue[i];
			if (typeof(o) == "function" && o.target == obj && o.func == func) {
				queue.splice(i, 1);
				return;
			}
		}
	}
}
Скажем есть класс
Код:
import mx.utils.Delegate;
//
class MyClass {
	var id;
	function MyClass(ID) {
		id = ID;
	}
	function addEvent(event, obj) {
		obj.addEventListener(event, Delegate.create(this, report));
	}
	function report(obj) {
		trace(id+"  "+obj.type);
	}
}
В первом кадре пишем:
Код:
import mx.events.EventDispatcher;

var mo = new Object();
EventDispatcher.initialize(mo);  // Создали вещатель

myC1 = new MyClass("myC1");  
myC1.addEvent("onEvent", mo);  // Создали экземпляр myClass и подписали его на onEvent

myC2 = new MyClass("myC2");
myC2.addEvent("onEvent", mo); // Создали контрольный экземпляр

mo.dispatchEvent({type:"onEvent"});  //  trace  myC2  onEvent  myC1  onEvent
trace("_____________________________________________");
DelegateRemover.removeDelegate(mo, "onEvent", myC1, myC1.report); // удалили
mo.dispatchEvent({type:"onEvent"});  // trace myC2  onEvent
__________________
...Тебе страшно? Мне - нет.


Последний раз редактировалось Ромастый; 20.12.2006 в 18:12.
Старый 20.12.2006, 18:29
etc вне форума Посмотреть профиль Найти все сообщения от etc
  № 2  
Ответить с цитированием
etc
Et cetera
 
Аватар для etc

Регистрация: Sep 2002
Сообщений: 30,784
Что-то мне подсказывает, что при таком подходе ты можешь удалить не тот обработчик…

Старый 20.12.2006, 18:32
Ромастый вне форума Посмотреть профиль Отправить личное сообщение для Ромастый Найти все сообщения от Ромастый
  № 3  
Ответить с цитированием
Ромастый
 
Аватар для Ромастый

Регистрация: Jan 2004
Адрес: На чердаке.
Сообщений: 1,112
Цитата:
Сообщение от __etc
Что-то мне подсказывает, что при таком подходе ты можешь удалить не тот обработчик…
Есть такой момент... но только в том случае, если создано более одного делегата.
А смысл вешать два и более делегатов на одно событие?
__________________
...Тебе страшно? Мне - нет.


Последний раз редактировалось Ромастый; 20.12.2006 в 18:37.
Старый 20.12.2006, 18:37
etc вне форума Посмотреть профиль Найти все сообщения от etc
  № 4  
Ответить с цитированием
etc
Et cetera
 
Аватар для etc

Регистрация: Sep 2002
Сообщений: 30,784
Ну случаев, когда обработчиков больше одного может быть много.
Три варианта:
1) Написать свой EventDispatcher (или найти более правильный, который работает по типу EventDispatcher в AS3, там не требуется делегата)

2) Написать отдельный класс, который будет хранить ссылку на делегированную функцию и по вызову убивать подписку.

3) Хранить ссылку внутри класса (нерационально)

Старый 20.12.2006, 18:45
Ромастый вне форума Посмотреть профиль Отправить личное сообщение для Ромастый Найти все сообщения от Ромастый
  № 5  
Ответить с цитированием
Ромастый
 
Аватар для Ромастый

Регистрация: Jan 2004
Адрес: На чердаке.
Сообщений: 1,112
Цитата:
Сообщение от __etc
Ну случаев, когда обработчиков больше одного может быть много.
Хм... поясни. Несколько раз подписать одну и ту же функцию на одно событие? Зачем?
Во всех прочих случаях удаляется нужный обработчик.

Цитата:
Сообщение от __etc
3) Хранить ссылку внутри класса (нерационально)
Ага, замучался )
__________________
...Тебе страшно? Мне - нет.

Старый 20.12.2006, 20:15
Ромастый вне форума Посмотреть профиль Отправить личное сообщение для Ромастый Найти все сообщения от Ромастый
  № 6  
Ответить с цитированием
Ромастый
 
Аватар для Ромастый

Регистрация: Jan 2004
Адрес: На чердаке.
Сообщений: 1,112
В порядке теста навешал до двух десятков различных - все работает, удаляется только нужный.
ПРоблемы возникают только при многократном:
Код:
myObject.addEventListener("onEvent", Delegate.create(MyOtherObject, method));
myObject.addEventListener("onEvent", Delegate.create(MyOtherObject, method));
... и т.д.
Лечится исключительно опять же многократным вызовом:
Код:
DelegateRemover.removeDelegate(myObject, "onEvent", MyOtherObject, method);
DelegateRemover.removeDelegate(myObject, "onEvent", MyOtherObject, method);
...
Но повторюсь - не вижу смысла несколько раз вешать один и тот же обработчик на одно и тоже событие...

Так же вроде все нормально работает с макромедийными компонентами
__________________
...Тебе страшно? Мне - нет.

Старый 07.02.2007, 16:59
Ромастый вне форума Посмотреть профиль Отправить личное сообщение для Ромастый Найти все сообщения от Ромастый
  № 7  
Ответить с цитированием
Ромастый
 
Аватар для Ромастый

Регистрация: Jan 2004
Адрес: На чердаке.
Сообщений: 1,112
Гыгы.
Удаляются все подписчики-клоны, созданные Delegate'ом, ежели цикл for заменить на for in и убрать нафих выход из метода.

Код:
class DelegateRemover {
	public static function removeDelegate(dispatcher, event, obj, func) {
		var queue = dispatcher["__q_"+event];
		for (var i in queue) {
			var o = queue[i];
			if (typeof(o) == "function" && o.target == obj && o.func == func) {
				queue.splice(i, 1);
				
			}
		}
	}
}
__________________
...Тебе страшно? Мне - нет.

Старый 07.02.2007, 17:00
Ромастый вне форума Посмотреть профиль Отправить личное сообщение для Ромастый Найти все сообщения от Ромастый
  № 8  
Ответить с цитированием
Ромастый
 
Аватар для Ромастый

Регистрация: Jan 2004
Адрес: На чердаке.
Сообщений: 1,112
Стормозил
__________________
...Тебе страшно? Мне - нет.

Старый 07.02.2007, 17:17
etc вне форума Посмотреть профиль Найти все сообщения от etc
  № 9  
Ответить с цитированием
etc
Et cetera
 
Аватар для etc

Регистрация: Sep 2002
Сообщений: 30,784
Кстати, Нокс предлагал решение удаления типа arguments.caller.removeEventListener ('someEvent',arguments.callee)


Последний раз редактировалось etc; 07.02.2007 в 17:46.
Старый 07.02.2007, 17:43
Nirth вне форума Посмотреть профиль Отправить личное сообщение для Nirth Посетить домашнюю страницу Nirth Найти все сообщения от Nirth
  № 10  
Ответить с цитированием
Nirth
4AM Games
 
Аватар для Nirth

блогер
Регистрация: Nov 2002
Адрес: Sofia
Сообщений: 6,264
Записей в блоге: 1
Отправить сообщение для Nirth с помощью ICQ Отправить сообщение для Nirth с помощью AIM Отправить сообщение для Nirth с помощью MSN Отправить сообщение для Nirth с помощью Yahoo Отправить сообщение для Nirth с помощью Skype™
А чем не подходит вариант которым польюзуются тысячи программистов на C#

Код:
var onSomeEventDelegate:Function = Delegate.create(...);

myInstance.addEventDispatcher("someEvent", onSomeEventDelegate);
myInstance.removeEventDispatcher("someEvent", onSomeEventDelegate);
__________________
Я перестал переписывать, начал редактировать, еще лет 15 и я стану писателем ^_^

Создать новую тему Ответ Часовой пояс GMT +4, время: 10:37.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 10:37.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.