1
votes

I am trying to remove a pointer in an NSMutableArray that points to an object in another array without deleting the object itself. E.g.:

// In ViewController.m – Code abridged and somewhat simplified

@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *objectPool;
@property (nonatomic, strong) NSMutableArray *objectsOwnedByFriend;
@property (nonatomic, strong) NSMutableArray *objectsOwnedByMe;
- (void)transferPointerToObjectFromFriendToMe;
- (void)copyPointerToObjectFromFriendToMe;
@end

@implementation ViewController

@synthesize objectPool = _objectPool;
@synthesize objectsOwnedByFriend = _objectsOwnedByFriend;
@synthesize objectsOwnedByMe = _objectsOwnedByMe;

- (void)setObjectPool:(NSMutableArray *)objectPool
{
    _objectPool = objectPool;
}

- (NSMutableArray *)objectPool
{
    if (!_objectPool) _objectPool = [[NSMutableArray alloc] initWithArray:self.objects]; // self.objects is a mutable array containing multiple NSObjects
    return _objectPool;
}

- (void)setObjectsOwnedByFriend:(NSMutableArray *)objectsOwnedByFriend
{
    _objectsOwnedByFriend = objectsOwnedByFriend;
}

- (NSMutableArray *)objectsOwnedByFriend
{
    if (!_objectsOwnedByFriend)
    {
        _objectsOwnedByFriend = [[NSMutableArray alloc] init];
        [_objectsOwnedByFriend addObjectsFromArray:self.objectPool];
    }
    return _objectsOwnedByFriend;
}

- (void)setObjectsOwnedByMe:(NSMutableArray *)objectsOwnedByMe
{
    _objectsOwnedByMe = objectsOwnedByMe;
}

- (NSMutableArray *)objectsOwnedByMe
{
    if (!_objectsOwnedByMe) _objectsOwnedByMe = [[NSMutableArray alloc] init];
    return _objectsOwnedByMe;
}

- (void)transferPointerToObjectFromFriendToMe
{
    [self.objectsOwnedByMe addObject:[self.objectsOwnedByFriend lastObject]];
    [self.objectsOwnedByFriend removeLastObject];
}

- (void)copyPointerToObjectFromFriendToMe
{
    [self.objectsOwnedByMe addObject:[self.objectsOwnedByFriend lastObject]];
}

@end

In the above code, when I use transferPointerToObjectFromFriendToMe, removing the last object removes both the pointer to it in self.objectsOwnedByFriend (as I want) and also the object itself in self.objectPool (which I don't want to happen).

What I would like is an array (self.objectPool) that contains all of the actual objects and then two mutable arrays (self.objectsOwnedByFriend and self.objectsOwnedByMe) that contains pointers to objects in self.objectPool and the ability to add and remove more pointers referencing objects in self.objectPool to self.objectsOwnedByFriend and self.objectsOwnedByMe.

Also, when I use either transferPointerToObjectFromFriendToMe or copyPointerToObjectFromFriendToMe, the object doesn't seem to be added properly, as a subsequent check via self.objectsOwnedByMe.count results in 0 instead of 1.
SOLUTION = My lazy instantiation for self.objectsOwnedByMe was missing in my original code :S
I was able to check whether self.objectsOwnedByMe was properly created via:

NSLog(@"self.objectsOwnedByMe = %@", self.objectsOwnedByMe);

** My first StackOverflow question! ** I hope I was clear...couldn't find a a similar question so apologies if I missed an old thread. Let me know if you need more info to diagnose. (I am trying to learn Obj-C.)

3
Instead of editing your original question to include the solution you should actually submit an answer and mark that answer as selected. Think about it from the perspective of someone searching for a answer coming from google. They like to find well posed questions and answers that have been accepted. - slayton
BTW, welcome to SO I hope you enjoy your stay - slayton
Now I see...hidden at the bottom of the page! Thanks. - Ken M. Haggerty

3 Answers

1
votes

Typo :P Sorry peeps. In my actual code in Xcode I had:

- (void)setObjectPool:(NSMutableArray *)objectPool
{
    _objectPool = objectPool;
}

- (NSMutableArray *)objectPool
{
    if (!_objectPool) _objectPool = [[NSMutableArray alloc] initWithArray:self.objects];
    return _objectsOwnedByFriend;
}

I think my mistake is super obvious (and if not, the mistake was that my getter for objectPool was returning _objectsOwnedByFriend...copy/paste error that I somehow missed).

Everything works now!

0
votes

This is very peculiar and confusing code. I suspect the problem is that something is calling one of the setters, -setObjectPool: or -setObjectsOwnedByFriend:, with the array of the other object. Those setters simply make the ivar refer to the object that was passed in. Because of that, they are very prone to lead to objects being shared.

Typically, a property like that would be declared and implemented with copy semantics.

0
votes

It looks like self.objectsOwnedByMe is never initialized and you are therefore always working with nil instead of an actual NSMutableArray.

Somewhere (perhaps in a custom getter for objectsOwnedByMe as below?) you need to create an array before you start using it:

- (NSMutableArray *)objectsOwnedByMe {
    if (_objectsOwnedByMe == nil) {
        _objectsOwnedByMe = [[NSMutableArray alloc] init];
    }
    return _objectsOwnedByMe;
}

This would explain both problems: Since it is nil it never retains the objects and therefore they go away when removed from the other array, and also why they are never added to the _objectsOwnedByMe array.