0

I need to make a "clone" of an array to another, but the thing is that when I modify my copied Array, the original is modified too. Using hard copy is not working as I expect.

I'm initializing an array like this:

NSMutableArray *otherArray = [[NSMutableArray alloc] initWithArray: myList copyItems:YES];

where myList is a NSArray that came as a parameter in my function. The thing is when I need to return myList, it's content has been modified when I modify my otherArray

I tried making a hard copy like:

NSMutableArray* algo = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:myList]];

But, some of the properties are not converted, and a nil value is assigned to them.

Also I tried with this:

NSMutableArray *otherArray = [myList mutableCopy];

Well, the obvious question is: How can I modify a copied object without modifying the original one?

Thanks!

EDIT: Here is my entire function.

    RAC(self,filteredPacks) = [RACSignal combineLatest:@[self.searchBoxSignal, self.packListsSignal]
                                                   reduce:^NSArray *(NSString *filterString, NSArray *packList) {

                                                       NSMutableArray *sweetHelper = [[NSMutableArray alloc] init];
                                                       NSMutableArray* packListCopy = [NSKeyedUnarchiver unarchiveObjectWithData:
                                                                               [NSKeyedArchiver archivedDataWithRootObject:packList]];

                                                       filterString = [filterString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

                                                       if ([filterString length] > 0)
                                                       {
                                                          for(PackList *theList in packListCopy){
                                                              NSMutableIndexSet *indexesToDelete = [NSMutableIndexSet indexSet];
                                                               NSUInteger currentIndex = 0;
                                                               for(Pack *thePack in theList.resolved_packs){

                                                                   if([thePack.name rangeOfString:filterString options:NSCaseInsensitiveSearch].location == NSNotFound){
                                                                       [indexesToDelete addIndex:currentIndex];
                                                                   }
                                                                   currentIndex++;
                                                                 }
                                                               [theList.resolved_packs removeObjectsAtIndexes:indexesToDelete];
                                                               [theList.packs removeObjectsAtIndexes:indexesToDelete];

                                                               [sweetHelper addObject:theList];
                                                           }
                                                           return sweetHelper;
                                                       }
                                                       else
                                                       {
                                                           return self.originalList;
                                                       }
                                                   }
                                  ];
FelipeDev.-
  • 3,113
  • 3
  • 22
  • 32
  • The mutableCopy shoudl do as well as just copy would do it. However, you would really copy the array only but not the objects within the array. Are you really referring to the array to be copied or would you need to copy the contained objects too? – Hermann Klecker Mar 25 '14 at 14:37
  • A small complete self-contained example demonstrating the problem would be helpful. – Martin R Mar 25 '14 at 14:38
  • @MartinR is right. You should build your exaple for your own learning too. BTW, the copyItems:YES would generate copies of all contained objects anyway. There must be something else wrong in your code. – Hermann Klecker Mar 25 '14 at 14:40
  • @HermannKlecker Edit done. I put my entire function. Please take a look and tell me if there is something wrong. I need to copy all the object inside my array. – FelipeDev.- Mar 25 '14 at 14:56
  • @MartinR Ok, self-contained example added – FelipeDev.- Mar 25 '14 at 14:56
  • @FelipeDev.-: That's not a self-contained example. It relies on ReactiveCocoa (and I have no experience with that), and on input variables and data types that are unknown to us. - A self-contained example is something that we can copy into an Xcode project and run it. – Martin R Mar 25 '14 at 15:32
  • You have return self.originalList in your code. Code that completely bypasses any array copy. Are you sure you're even trying to use the copy and not returning self.originalList? – stevesliva Mar 25 '14 at 16:46
  • I guess that `NSKeyedUnarchiver` and `NSKeyedArchiver` are used just to try to create really a copy of the array and all its items. This line is what you ask to be replaced with something that REALLY copies all the data. I gutess you are on the wrong track here, because that, and other methods suggested, should create independent copies, meaning new instances of all arrays and items and arrays in items etc. pp. – Hermann Klecker Mar 25 '14 at 17:36
  • All this happens in a block statement. Meaning this is not neccessarily executed at a point in time where you expect it. Please add more code, where the block is actually created and called and where its return value is tested. Explain why you believe that the elements in the "copy" are identical to the originals. Try nslogging their addresses (that would show whether they are copies or not). And make sure that the `else` branch with the `return self.originalList;` in it has never been executed. – Hermann Klecker Mar 25 '14 at 17:39

1 Answers1

0

Well, I found the solution using this answer and this comment in the same question.

As I said in my question:

"I tried making a hard copy like:

NSMutableArray* algo = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:myList]];

But, some of the properties are not converted, and a nil value is assigned to them."

Well, the properties that were not converted, they weren't because they are custom objects, An I didn't implemented the initWithCode and encodeWithCoder methods. So, when I added those methods to my customObjectClass, my Arrays were hard copied with all their elements.

A little example about what I did:

In my SomeCustomObject.h I should implements NSCoding:

@interface SomeCustomObject : NSObject <NSCoding> {
  NSMutableArray * __packs;
  int __type;
  Link * __selfRef;
  NSMutableArray * __resolved_packs;
}

And in my subclass of SomeCustomObject I got something like:

- (id)initWithCoder:(NSCoder *)decoder {
 if (self = [super init]) {
    __packs = [decoder decodeObjectForKey:@"packs"];
    __type = [decoder decodeIntForKey:@"type"];
    __selfRef = [decoder decodeObjectForKey:@"selfRef"];
    __resolved_packs = [decoder decodeObjectForKey:@"resolved_packs"];
 }
 return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
  [encoder encodeObject:__packs forKey:@"packs"];
  [encoder encodeInt:__type forKey:@"type"];
  [encoder encodeObject:__selfRef forKey:@"selfRef"];
  [encoder encodeObject:__resolved_packs forKey:@"resolved_packs"];
}

I hope this be useful to somebody :)

Community
  • 1
  • 1
FelipeDev.-
  • 3,113
  • 3
  • 22
  • 32