12 Replies Latest reply on Dec 13, 2006 6:11 PM by schjlatah

    ArrayCollection.addItem( not just a reference! )

    schjlatah
      What I'm trying to do is something like ArrayUtilities.duplicate(object), but using the ArrayCollection. Also, I haven't been able to find ArrayUtilities.duplicate (it was referenced in the O'Reily book on AS3).
      I have an object of a custom class, and I want to make an array of them where I can change the original object and not have it change the array.

      For Example:

      import controls.Source; //Source is a custom class I created in the controls dir/folder

      [Bindable] public var source:Source;
      source.field1="something"; //where field1 is defined as a String in the Source class
      [Bindable] public var destination:ArrayCollection = new ArrayCollection();

      public function addSourceToDestination():void
      {
      destination.addItem(source);
      source.field1="anything else";
      Alert.show(source.field1);
      Alert.show(destination[0].field1);
      // will show two alert boxes that both say 'anything else'
      }

      /*
      How do I fix this? I need to save the contents of a form into an array, then be able to clear the form for re-population and not have those changes reflected until I add the object to the next position in the array.
      I'll address modifying the contents of the Array later on, that shouldn't be as difficult.

      Can someone PLEASE help me? I've been pulling my hair out for 3 days, now I'm running out of hair.
      */
        • 1. Re: ArrayCollection.addItem( not just a reference! )
          DavidWhewell Level 1
          It may be stating the obvious, but can you not just extend ArrayCollection() and implement a clone() method on it?
          • 2. ArrayCollection.addItem( not just a reference! )
            schjlatah Level 1
            I may be missunderstanding how you ment to implement that, but I changed my Source class to extend ArrayCollection then after getting rid of the compiler errors (overloading where not permitted) I couldn't get it to .clone(). I also tried extending ArrayCollection in my main class (the code snippet from above is in a custom class that implements another custom class) and that didn't work either.

            I'm not sure that extending ArrayCollection is the right way to go. I don't need to add an Array to an Array, I need to add an Object to an Array by value, not reference. I know that the problem is with the way AS3 handles composite data types. It makes sense from a memory saving side, but it does limit functionality in certain instances. What I need a workaround, as I'm sure there is.

            I need ArrayCollectionVariable[n] =(set by value)= ObjectVariable;
            then I clear the values in ObjectVariable add new values to it, then add those new values to ArrayCollectionVariable[n+1] and so on, so that ArrayCollectionVariable[x] would be a snapshot of what ObjectVariable would've been when it was added (via a fancy function stored in a class that this all will take place in).
            • 3. Re: ArrayCollection.addItem( not just a reference! )
              schjlatah Level 1
              Am I the only one having this problem? Someone please help... superman? batman? codeman?
              • 4. Re: ArrayCollection.addItem( not just a reference! )
                jpwrunyan Level 1
                There is a way to clone data. One way I use is making a function that copys via a BitArray. It's in the AS3 docs. Try looking there for it. Of course, the problem you will inevitably run into even if you do clone data using that method is that the flex framework uses a UID to flag independent objects as actually being the same (sort of tantamount to being a reference though the mermory used is double). So you will also have to somehow change the UID even after you clone.

                by the way, since I can't find a link, here is a clone function:

                function clone(source:Object):* {
                if (source is XML) {
                //XML is special
                return XML(source).copy();
                }
                var ba:ByteArray = new ByteArray();
                ba.writeObject(source);
                ba.position = 0;
                return ba.readObject()
                }

                then, when I use it with, for example, a dataProvider:
                var copy_obj:Object = clone (my_dp.getItemAt(n));
                //the data is exactly the same, but it's not supposed to be linked, so...
                copy_obj.mx_internal_uid = UIDUtil.createUID();
                //now add it as a copy back to the ArrayCollection
                my_dp.addItem(copy_obj);

                Hope this helps.
                • 5. Re: ArrayCollection.addItem( not just a reference! )
                  ntsiii Level 3
                  It is not a generic solution, but you could "new" a source object, sets properties, then add it to the ArrayCollection.

                  Tracy
                  • 6. Re: ArrayCollection.addItem( not just a reference! )
                    schjlatah Level 1
                    Tracy,
                    I've tried that, but when I add it to the ArrayCollection that's when I get reference to the "new" source object in the ArrayCollection. I think that jpwrunyan's response may work, but every time I try it halts my computer. I think I'm doing something wrong, or my computer is having logic issues (also not unheard of).
                    Please keep the solutions coming.
                    • 7. ArrayCollection.addItem( not just a reference! )
                      jpwrunyan Level 1
                      Wow, it's halting your computer? How big is the object you are copying?
                      Assuming I understand Tracy's meaning,
                      the problem with making a "new Object()" and setting properties is that if the property itself is an object, then you get a sub-reference:
                      ex:
                      me = new Human();
                      me.myCat = new Cat();
                      //copy
                      myClone = new Human(); //independent object
                      for (var p:String in me) {
                      myClone[p] = me[p];
                      }

                      by the above logic, although primitive property values get cloned, objects (like Cat) do not. The result: me and myClone both own the same cat. So if my cat dies, myClone's does, too (same cat, remember).

                      It might be a little slower, but using the ByteArray technique guarantees that the cat gets cloned as well. Now why it should be breaking your computer... that you'll have to show the code for.
                      • 8. Re: ArrayCollection.addItem( not just a reference! )
                        dberkowicz Level 1
                        I have the same issue with cloning. I have tried the clone via a ByteArray, but this returns an object that I cannot cast back to my original type. Anybody have any ideas about this? Any help much appreciated.
                        • 9. Re: ArrayCollection.addItem( not just a reference! )
                          jpwrunyan Level 1
                          What? You can't cast it back? What does your code look like? I have yet to encounter this problem though I haven't strenuously tested for it. If you are using a complex class, you may not want to use ByteArray to clone anyway, though. It is probably faster to make a new instance, copy all the primitive properties, and then clone all Object/Array properties.
                          • 10. Re: ArrayCollection.addItem( not just a reference! )
                            ur_dtrain Level 1
                            ObjectUtil.copy()

                            x.addItem(ObjectUtil.copy(y.getItemAt(i)));
                            • 11. Re: ArrayCollection.addItem( not just a reference! )
                              schjlatah Level 1
                              Thanks everybody. I haven't gotten a chance to try any more of the responses yet; that's next week. This week will be spent in ADO.NET 2 (no me gusta).

                              I was ashamed to reply back to why it would lock up my computer. I found where I was recursively extending two classes. I hope that ObjectUtil will work, that looks exactly like what I'm looking for.
                              Thanks everybody.
                              If there is any more methods to try, please keep 'em coming.
                              • 12. Re: ArrayCollection.addItem( not just a reference! )
                                schjlatah Level 1
                                Sorry I haven't gotten back in a while. I have been busy. The ByteArray copying worked like a charm. That was it. I NEVER would've thought of that on my own. jpwrunyan I owe you one.