2

I'm having trouble removing items from my NSMutableArray. I'm extremely new to Objective-C, so please bear with me.

So far, I have the following: I'm trying to remove a line from the array if it has certain text inside. I cannot do this while fast-enumerating, so I'm trying to store the index, for removal after the enumeration has finished. However, I'm being told that this makes a pointer from an integer without a cast. Confused!

//First remove any previous Offending entry.
//Read hostfile into array.
NSString *hostFileOriginalString = [[NSString alloc] initWithContentsOfFile:@"/etc/hosts"];
NSMutableArray *hostFileOriginalArray = [[hostFileOriginalString componentsSeparatedByString:@"\n"] mutableCopy];
NSInteger hostFileOffendingLocation;

//Use a for each loop to iterate through the array.
for (NSString *lineOfHosts in hostFileOriginalArray) {

    if ([lineOfHosts rangeOfString:@"Offending"].location != NSNotFound) {

    //Offending entry found, so remove it.
    //[hostFileOriginalArray removeObject:lineOfHosts];

    hostFileOffendingLocation = [hostFileOriginalArray indexOfObject:lineOfHosts];
    //NSLog(@"%@", hostFileOffendingLocation);
}

}
//Release the Array. 
[hostFileOriginalArray release];

//Remove offending entry from Array.
[hostFileOriginalArray removeObject:hostFileOffendingLocation];
jscs
  • 63,694
  • 13
  • 151
  • 195
Phill
  • 21
  • 2
  • This makes a pointer from an integer without a cast because you are passing an integer to `removeObject:`. I think `removeObjectAtIndex:` is what you are after. Also, why are you releasing the array before trying to remove the object? – albertamg May 06 '11 at 19:12

3 Answers3

0

My real question is why are you releasing your array before modifying it

try moving

[hostFileOriginalArray release];

to after

[hostFileOriginalArray removeObject:hostFileOffendingLocation];
Dan F
  • 17,654
  • 5
  • 72
  • 110
  • thanks. I've altered it now. However, the original problem still exists. – Phill May 06 '11 at 19:01
  • Is it showing up as removed from the mutable array and not from the original, or is it still showing up in both? I suspect it is because you are using mutablecopy and it is creating a copy of the data – Dan F May 06 '11 at 19:08
  • 1
    hostFileOffendingLocation is the index of the object, not the object itself. You want to use `removeObjectAtIndex:`, not `removeObject`. – albertamg May 06 '11 at 19:13
  • Yeah I missed that, thats what happens when I read through code too quickly – Dan F May 06 '11 at 19:15
0

You can do this without the loop by calling [hostFileOriginalArray removeObjectIdenticalTo:@"Offending"];

Note that it will remove multiple instances of the offending object, but that looks like what you want anyway. It will also do the operation in a fast way, without you having to worry about the implementation detail of which loop to use.

As a general rule (especially with the really commonly used objects like containers and NSString), check the class reference to see if Apple already has a way of doing what you want to do. It makes your code more readable to other Cocoa users (including future you), and reduces code maintenance- you're now leaving it up to Apple to add new technologies like Fast Enumeration to their code, and you get it for free when you link against new versions of the SDK.

Also, you should probably return hostFileOriginalArray at the end of the function, so it can do something useful- you can return it as an autoreleased object.

matthias
  • 2,419
  • 1
  • 18
  • 27
  • removeObjectIdenticalTo does sound very much like what I'm after. However I can't seem to get it to match in the same way that rangeOfString does in my above code. As you can probably guess, the code is editing the hosts file, which will contain an changing ip address followed by an alias. I need to remove the whole line, which rangeOfString was allowing me to do. – Phill May 06 '11 at 19:02
  • Ah, I missed that it was looking for @"Offending" as a substring. Try building an NSPredicate (using, perhaps, [NSPredicate predicateWithBlock:] where the block returns YES if @"Offending" is not found, or perhaps using the string matching found at: http://arstechnica.com/apple/guides/2009/04/cocoa-dev-the-joy-of-nspredicates-and-matching-strings.ars). – matthias May 06 '11 at 19:17
  • actually, I've been able to save the offending line to a string, and then remove it using removeObjectIdenticalTo :) thanks again. – Phill May 06 '11 at 19:19
  • removeObjectIdenticalTo: searches by (id), that is will only remove the actual object, not objects that have the same value, use removeObject: instead. – Grady Player May 06 '11 at 22:22
  • you really want removeObjectAtIndex: anyway. – Grady Player May 06 '11 at 22:26
0
//Remove offending entry from Array.
[hostFileOriginalArray removeObjectAtIndex:hostFileOffendingLocation];

//Release the Array. 
[hostFileOriginalArray release];

you should have been getting compiler warnings... take a look at them, they are usually very helpful, I always try to have 0 warnings... that way I know where I have done something careless.

Grady Player
  • 14,399
  • 2
  • 48
  • 76