Как я могу скопировать ArrayCollection переданных объектов в ActionScript? - PullRequest
1 голос
/ 27 октября 2011
public function create():ArrayCollection{

            var index:int = 0;
            var data:ArrayCollection = new ArrayCollection();
            var length:int = originalData.length;

            for(index; index < length; index++){
                data.addItem(originalData[index]);
            } 

            return data;
        }
  • originalData - это исходное состояние моих данных из базы данных.
  • data - это копия originalData, которая использовалась в качестве поставщика для моего компонента List.
  • Есть кнопка, которую я использую для вызова функции create () выше, это означает, что я хочу отменить все изменения в данных и вернуться ко всему, что у меня есть в originalData.

Но когда я отлаживаюВ моей функции originalData есть все изменения, сделанные в данных.

Когда я использую

list.selectedItem.thing = "new string";

должен изменять данные [index] .thing, потому что данные мой List.dataprovider.но он также изменяет originalData [index] .thing, и эта коллекция не использовалась ни для чего, кроме как для создания собственной копии!

Я не знаю, почему это происходит.Я не знал, как сформулировать это поведение как запрос Google.

Пожалуйста, если вы не понимаете вопрос, прокомментируйте его, чтобы я мог попытаться сделать его более понятным.Это заняло больше времени, чем его функциональность.

РЕДАКТИРОВАТЬ:

Я также пробовал это, но это не работает:

public function create():ArrayCollection{

            var index:int = 0;
            var data:ArrayCollection = new ArrayCollection();
            var length:int = originalData.length;

            for(index; index < length; index++){
// initializing a Item object.
                var dataItem:Item = new Item();
                dataItem = originalData[index] as Item;
                data.addItem(dataItem);
            } 

            return data;
        }

РЕДАКТИРОВАТЬ 2:

Основываясь на ваших ответах и ​​некоторых исследованиях, я придумал эту универсальную функцию для копирования arrayCollections из пользовательских объектов.

public static function copy(objectClassName:String, objectClass:Class, arrayCollection:ArrayCollection):ArrayCollection{
            var index:int = 0;
            var length:int = arrayCollection.length;
            var copy:ArrayCollection = new ArrayCollection();

            for(index; index < length; index++){
                registerClassAlias(objectClassName,objectClass);
                copy.addItemAt(ObjectUtil.copy(arrayCollection.getItemAt(index)) as objectClass,index);
            }
            return copy;
        }

Ответы [ 4 ]

4 голосов
/ 27 октября 2011

Как говорит Том, это потому, что AS3 проходит по ссылке. Если вы не хотите изменять исходные значения, то, как говорит Том, снова создайте их копии.

К счастью, AS3 имеет утилиту для этого - ObjectUtils.copy . Попробуйте этот код вместо вашего оригинала:

public function create():ArrayCollection{

            var index:int = 0;
            var data:ArrayCollection = new ArrayCollection();
            var length:int = originalData.length;

            for(index; index < length; index++){
                data.addItem(mx.utils.ObjectUtil.copy(originalData[index]));
            } 

            return data;
        }

Обратите внимание, что copy () возвращает универсальный объект. Если вы хотите получить доступ к любому из его свойств безопасным для типа способом, вам придется привести его к его типу.

Немного подробнее о соглашении о передаче по ссылке. Допустим, у нас есть элементы a, b и c, плавающие в памяти. Вы помещаете их в массив (originalData). originalData теперь содержит ссылки на a, b и c. Затем вы создаете ArrayCollection и вставляете (снова) ссылки на a, b, c. Объекты a, b и c не являются тем, что хранится ни в массиве, ни в коллекции ArrayCollection. Поэтому, когда вы обновляете originalData [0], вы получаете ссылку на объект (a) и обновляете его.

Аналогично, когда вы обновляете ArrayCollection.getItemAt (0), вы получаете ту же ссылку и обновляете базовый объект, поэтому вы получаете поведение, которое вы получаете. Создание копии и ее вставка означает, что вы ссылаетесь на совершенно новый объект.

0 голосов
/ 01 октября 2012

Вам нужно сделать вызов registerClassAlias ​​для каждого из классов внутри вашей коллекции, затем просто использовать функцию clone с предложенным выше ByteArray, и он будет работать нормально. Ключ заключается в том, чтобы сделать вызов registerClassAlias ​​для каждого типа внутри ArrayCollection, который вы хотите сохранить. В моем случае:

var productGroupClassName:String = getQualifiedClassName(ProductGroup);
                registerClassAlias( productGroupClassName, ProductGroup );
                var productClassName:String = getQualifiedClassName(Product);
                registerClassAlias( productClassName, Product );
                //Need to create a copy so the original values will not be altered
                dataProvider = copyTypeSafe(EnalityData.productsInfo);
0 голосов
/ 28 октября 2011

Чтобы создать глубокую копию массива и сохранить тип, используйте следующий метод:

public static function clone(source:Object):* 
{ 
    var myBA:ByteArray = new ByteArray(); 
    myBA.writeObject(source); 
    myBA.position = 0; 

    return(myBA.readObject()); 
}

Это способ, предложенный Adobe .

Обновление : идея для функции безопасного копирования типов

public static function copyTypeSafe( ac:ArrayCollection ):ArrayCollection
{
    var cloneAc:ArrayCollection = new ArrayCollection();

    if( ac.length ==  0 ) {
        return cloneAc;
    }

    var className:String = getQualifiedClassName( ac.getItemAt(0) );
    registerClassAlias( className, (getDefinitionByName( className ) as Class ) );

    for each (var obj:Object in ac) 
    {
        cloneAc.addItem( ObjectUtil.copy( obj ) );
    }

    return cloneAc;

}
0 голосов
/ 27 октября 2011

Я не привык к actionScript, но мне кажется, что вы помещаете ссылки на объекты из одного arrayCollection в другой arrayCollection. Поэтому, если вы измените эти объекты, это будет отражено в обоих массивах arrayCollections, поскольку они ссылаются на одни и те же объекты.

Чтобы избежать этого, вы должны сделать копии из исходных объектов для помещения в новую коллекцию arrayCollection.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...