spaderdabomb
spaderdabomb

Reputation: 942

Creating a copy of an NSMutableArray with custom objects

I've been searching around for the solution to this for quite a while, and none of the other threads have helped. Basically, what I want to accomplish is creating an array of custom objects as a singleton, load them into my level, then create a copy of them since variables assigned to these objects will be manipulated. When the level is complete (or failed) though, I want these objects to remain the same so I can reload them.

Below are some things I've tried.

- (void)spawnStartTiles {
    //where _puzzleGridTilesArray and curLevel.gridTiles are NSMutableArrays
    [_puzzleGridTilesArray removeAllObjects];
    _puzzleGridTilesArray = [curLevel.gridTiles mutableCopy];
    CCLOG(@"tile in curlevel %@", curLevel.gridTiles[0]); //want these to log DIFFERENT objects
    CCLOG(@"tile in puzzle array %@", _puzzleGridTilesArray[0]);//want these to log DIFFERENT objects
}

The above logs the same object ID.

- (void)spawnStartTiles {
    //where _puzzleGridTilesArray and curLevel.gridTiles are NSMutableArrays
    _puzzleGridTilesArray = [self cloneArray:curLevel.gridTiles];
    CCLOG(@"tile in curlevel %@", curLevel.gridTiles[0]); //want these to log DIFFERENT objects
    CCLOG(@"tile in puzzle array %@", _puzzleGridTilesArray[0]);//want these to log DIFFERENT objects
}

-(NSMutableArray*)cloneArray:(NSMutableArray *)myArray {
    return [[NSMutableArray alloc] initWithArray: myArray];
}

Still logs same object ID.

- (void)spawnStartTiles {
    //where _puzzleGridTilesArray and curLevel.gridTiles are NSMutableArrays
    _puzzleGridTilesArray = [[NSMutableArray alloc] initWithArray:curLevel.gridTiles copyItems:YES];
    CCLOG(@"tile in curlevel %@", curLevel.gridTiles[0]); //want these to log DIFFERENT objects
    CCLOG(@"tile in puzzle array %@", _puzzleGridTilesArray[0]);//want these to log DIFFERENT objects
}

The above gives a runtime error. I think this is because the objects I am copying are a custom class named Tile. The class is a CCNode, and the .h file is below.

#import "CCNode.h"

@interface Tile : CCNode

@property (nonatomic, assign) NSInteger value;
@property (nonatomic, assign) NSInteger gemLevel;
@property (nonatomic, assign) BOOL mergedThisRound;
- (void)updateValueDisplay:(BOOL)bannerTiles difficultyMode:(int)difficultyMode;
- (void)updateOpacity:(NSInteger)opacityVariable;
- (void)tileHasBeenSelected:(BOOL)tileHasBeenTouched;

@end

Is there a way to somehow transform this class so that is can be copied? I've looked at http://www.techotopia.com/index.php/Copying_Objects_in_Objective-C and Implementing NSCopying and I'm still confused, so further help would be greatly appreciated. Thank you!

Upvotes: 0

Views: 87

Answers (1)

dalton_c
dalton_c

Reputation: 7171

You get an error because [[NSMutableArray alloc] initWithArray:curLevel.gridTiles copyItems:YES] calls copyWithZone: on each item in the array. Your items must conform to NSCopying for you to use this method, but this is the correct approach.

To implement NSCopying:

  1. Update your Tile class to add the protocol, i.e. @interface Tile : CCNode <NSCopying>
  2. Implement the method - (id)copyWithZone:(NSZone *)zone in your Tile implementation.
  3. In that method, allocate a new instance of Tile and assign all of it's properties to that of your current instance.

Upvotes: 6

Related Questions