Objective-C subclass initWithSuperClass - objective-c

The common Superclass of Rectangle and Circle is Shape.
If I initialize some shapes, what is a good way of converting the shape into a circle later and keeping the same properties set while it was a shape? Should I implement a initWithShape in the subclasses that looks something like this?
- (id) initWithShape:(Shape*)aShape {
self = (id) aShape;
// set circle or rectangle specific values
return self;
}
Does anyone have an example that I can look at?

Don't do what you just did. Think about what happens when you do this:
Shape *shape = ...;
Rectangle *rect = [[Rectangle alloc] initWithShape:shape];
In the second line, an instance of Rectangle gets allocated. Then, the return value for initWithShape is just shape again, so the new Rectangle that we just allocated has been leaked!
The cast to id is also unnecessary—any Objective-C object can be implicitly cast to id.
I'm not entirely clear on what you're trying to do. Perhaps if you clarified your question, I could tell you what you should be doing.

You cannot change an object after it has been created, except by freeing it and creating a new one (which you can do in an init method, and is in fact quite often done for singletons or class clusters), but that is not really what you're after.
Give an existing Shape object, with some properties, your only real option is to create a new object based on the shape properties. Something like:
In Shape.m:
- (id) initWithShape:(Shape*)aShape {
self = [super init];
if (self != nil) {
// copy general properties
_x = aShape.x;
_y = aShape.y;
_color = [aShape.color copy];
}
return self;
}
In Circle.m:
- (id) initWithShape:(Shape*)aShape {
self = [super initWithShale:aShape];
if (self != nil) {
// base properties on the class of the shape
if ( [aShape isKindOfClass:[Oval class]] ) {
// average the short and long diameter to a radius
_radius = ([(Oval*)aShape shortDiameter] + [(Oval*)aShape longDiameter])/4;
} else {
// or use generic Shape methods
_radius = aShape.size / 2;
}
}
return self;
}

If you have a reference to a Shape, and it might be a Rectangle or Pentagram or whatever, and you want to 'convert' to a circle (I guess you mean a circle with the same bounding box?), you have to create a new object. You can't change the class of an object after it's been created (except through very nasty low-level hacks.)
So yes, you would create an -initWithShape: method in class Circle. But the method would look like a normal init method, setting up the instance variables of the new Circle object ('self'). It would access properties of the given Shape, like its position and size, and set up the new object accordingly.

Why not implement a method in your shapes to take properties from other shapes rather than trying to replace the instance of the object altogether. It's probably safer.
// for rectangle
- (void) takePropertiesFrom:(Shape *) aShape
{
if ([aShape isKindOfClass:[Circle class]])
{
float radius = [aShape radius];
[self setWidth:radius * 2];
[self setHeight:radius * 2];
}
else
{
[self setWidth:[aShape width]];
[self setHeight:[aShape height]];
}
}
// for circle
- (void) takePropertiesFrom:(Shape *) aShape
{
if ([aShape isKindOfClass:[Rectangle class]])
[self setRadius:[aShape width] / 2];
else
[self setRadius:[aShape radius]];
}
Obviously you would want to set up a public interface for Shape that exposes the basic properties of a shape, such as height and width, and then you won't need to hard-code property stealing based on class type.

Related

Obj-C and SpriteKit - Changing a sprite value that is created randomly

I'm making a game using SpriteKit and Objective-C.
I have four different texture drops (Blue, Green, Orange and Red) that falls down on screen randomly.
In my ANBDropNode class I have this method:
+(instancetype)dropOfType:(ANBDropType)type {
ANBDropsNode *drop;
if (type == ANBDropTypeBlue) {
drop = [self spriteNodeWithImageNamed:#"bluedrop"];
} else if (type == ANBDropTypeGreen) {
drop = [self spriteNodeWithImageNamed:#"greendrop"];
} else if (type == ANBDropTypeOrange) {
drop = [self spriteNodeWithImageNamed:#"orangedrop"];
} else if (type == ANBDropTypeRed){
drop = [self spriteNodeWithImageNamed:#"reddrop"];
}
[drop setupPhysicsBody];
return drop;
}
And in my GamePlayScene these two:
-(void)addDrops {
NSUInteger randomDrop = [ANBUtil randomWithMin:0 max:4];
self.drop = [ANBDropsNode dropOfType:randomDrop];
float y = self.frame.size.height + self.drop.size.height;
float x = [ANBUtil randomWithMin:10 + self.drop.size.width
max:self.frame.size.width - self.drop.size.width - 10];
self.drop.position = CGPointMake(x, y);
[self addChild:self.drop];
}
-(void)update:(NSTimeInterval)currentTime {
if (self.lastUpdateTimeInterval) {
self.timeSinceDropAdded += currentTime - self.lastUpdateTimeInterval;
}
if (self.timeSinceDropAdded > 1) {
[self addDrops];
self.timeSinceDropAdded = 0;
}
self.lastUpdateTimeInterval = currentTime;
}
The question is (and it may sound a little dumber, I know): before the drop hits the ground it has already changed it value. If ANBDropNode *drop is a bluedrop, before it hits the ground the method randomly create another drop and change it value for greendrop, for example. But I don't want this behavior. I want the drop to continue with its value until it reaches the ground so I can detect its color in my didBeginContact method.
Sorry in advance for any english mistakes, as I'm not an native english speaker.
From your question I understand that the reason you are keeping a reference to the drop (self.drop) is to check what is its colour when it hits the ground.
So you could just delete that, and create a new SKSpriteNode object each time, instead of just changing the reference of the current property.
If you have any other reason for keeping a reference to that drop, just still keep a reference.
Note that doing any of the above, will not affect the code below.
I think that you were in the right direction (when asking about didBeginContact) but took the wrong approach/mindset, since there is no need to keep a reference when using didBeginContact, because you can get the nodes in contact from this method.
Anyway, here is the code + explanations
// MyScene.m
// First, conform to SKPhysicsContactDelegate, so you can get didBeginContact 'calls'
#interface MyScene () <SKPhysicsContactDelegate>
#end
#implementation MyScene
// Now add the following constant, that you'll use as the physics body category bit masks
static const uint32_t groundCategory = 0x01 << 0;
static const uint32_t dropsCategory = 0x01 << 1;
// Somewhere in your initialisation, set yourself to be the physicsWorld
// contact delegate, so you'll receive the didBeginContact 'calls',
// And also call setupGround method, that we will create in here as well
-(id)initSceneWithSize:(CGSize)size {
...
...
self.physicsWorld.contactDelegate = self;
[self setupGround];
...
}
// Here we will create the ground node, so we can detect when a drop
// Hits the ground.
// The reason that, in the below code, I am setting just the ground,
// and not the whole borders of the screen, is because the drops
// are added above the screen 'borders', and if we would make
// a 'frame' node, and not a 'ground' node, we will also receive
// contact delegate calls, when the nodes first enter the scene
// and hits the top 'border' of the frame
-(void)setupGround {
SKNode *groundNode = [SKNode node];
groundNode.strokeColor = [SKColor clearColor];
groundNode.fillColor = [SKColor clearColor];
// Not sure if the above two are mandatory, but better be safe than sorry...
// Here we set the physics body to start at the bottom left edge of the screen
// and be the width of the screen, and the size of 1 points
// Then, we also set its category bit mask
CGRect groundRect = CGRectMake(0, 0, self.size.width, 1);
groundNode.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:groundRect];
groundNode.physicsBody.categoryBitMask = groundCategory;
[self addChild:groundNode];
}
// Next we will modify your current method of creating drops, to also have
// their name property to holds the corresponding colour name
+(instancetype)dropOfType:(ANBDropType)type {
ANBDropsNode *drop;
if (type == ANBDropTypeBlue) {
drop = [self spriteNodeWithImageNamed:#"bluedrop"];
drop.name = #"Blue";
} else if (type == ANBDropTypeGreen) {
drop = [self spriteNodeWithImageNamed:#"greendrop"];
drop.name = #"Green";
} else if (type == ANBDropTypeOrange) {
drop = [self spriteNodeWithImageNamed:#"orangedrop"];
drop.name = #"Orange";
} else if (type == ANBDropTypeRed){
drop = [self spriteNodeWithImageNamed:#"reddrop"];
drop.name = #"Red";
}
[drop setupPhysicsBody];
return drop;
}
// In your setupPhysicsBody method of the drop, add the following to define
// the drop's bit mask, contact test, and collision.
// Make sure you are adding them AFTER setting the physics body, and not before.
// Since you revealed no code regarding this method, I will assume 'self' is
// referring to the drop, since you call this method on the drop.
-(void) setupPhysicsBody {
...
...
...
self.physicsBody.categoryBitMask = dropsCategory;
self.physicsBody.contactTestBitMask = groundCategory;
self.physicsBody.collisionBitMask = 0;
// The above code sets the drop category bit mask, sets its contactTestBitMask
// to be of the groundCategory, so whenever an object with drop category, will
// 'touch' and object with groundCategory, our didBeginContact delegate will
// get called.
// Also, we've set the collision bit mask to be 0, since we only want to
// be notified when a contact begins, but we don't actually want them both to
// 'collide', and therefore, have the drops 'lying' on the ground.
...
...
...
}
// Now we can set the didBeginContact: delegate method.
// Note that, as the name of the method suggests, this method gets called when a
// Contact is began, meaning, the drop is still visible on screen.
// If you would like to do whatever you want to do, when the drop leaves the screen,
// just call the didEndContact: delegate method
-(void)didBeginContact:(SKPhysicsContact *)contact {
// SKPhysicsContact have two properties, bodyA and bodyB, which represents
// the two nodes that contacted each other.
// Since there is no certain way to know which body will always be our drop,
// We will check the bodies category bit masks, to determine which is which
ANBDropsNode *drop = (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) ? (ANBDropsNode *)contact.bodyB.node : (ANBDropsNode *)contact.bodyA.node;
// In the above we are checking the category bit masks,
// Note that we set groundCategory to be 1, and dropsCategory to be 2,
// So we are checking which is higher.
// If bodyA bit mask is lower than bodyB bit mask, that means the bodyA is
// the ground, and bodyB is the drop, so we set the drop to be bodyB's node
// Else, we set it to be bodyA's node.
// Now you can easily get the drop colour from the name property we've set in
// the beginning. you can do some sort of if-else statement, that check
// 'if isEqualToString'. Here I just NSLog the colour
NSLog(#"%#", drop.name);
}
Good luck mate.
You can simply associate a property with the ANBDropsNode class which can be set when the drop is instantiated.
In the ANBDropsNode.h file,
#interface ANBDropsNode
#property (strong, nonatomic) NSString *dropColor; //This property will hold the value associated with the color.
Then in the dropOfType class method:
+(instancetype)dropOfType:(ANBDropType)type {
NSString *strDropColor;
if (type == ANBDropTypeBlue) {
strDropColor = #"bluedrop";
} else if (type == ANBDropTypeGreen) {
strDropColor = #"greendrop";
} else if (type == ANBDropTypeOrange) {
strDropColor = #"orangedrop";
} else if (type == ANBDropTypeRed){
strDropColor = #"reddrop";
}
ANBDropsNode *drop = [self spriteNodeWithImageNamed:strDropColor];
drop.dropColor = strDropColor;
[drop setupPhysicsBody];
return drop;
}
Now, in your collision detection delegate method, you can find out the color of the node by simply referring the dropColor property.

Showing a button when all 'enemy' ccsprites have been removed from scene

I am using SpriteBuilder to make a game. The objective is to destroy some CCSprites. I have 3 sprites on screen and are destroyed by another sprite, so the code must have something to do with when there are no more 'enemy' sprites remaining a next button must show. I have looked on the internet and are inexperienced with Cocos2D coding. Here is the code I have used to get rid of the 'enemy'
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair danald:(CCNode *)nodeA wildcard:(CCNode *)nodeB {
float energy = [pair totalKineticEnergy];
if (energy > 5000.f) {
[self danaldRemoved:nodeA];
}
}
If the object is hit with a certain speed it will call the method below
- (void)danaldRemoved:(CCNode *)Danald {
CCParticleSystem *explosion = (CCParticleSystem *)[CCBReader load:#"Explosion"];
explosion.autoRemoveOnFinish = TRUE;
explosion.position = Danald.position;
[Danald.parent addChild:explosion];
[Danald removeFromParent];
}
Thanks in an advanced, sorry if this question has been asked before but I cannot find it
Well I would suggest this method:
Create a variable where you store the number of sprites left. For example:
int spritesLeft;
And then initialize it to 0:
-(void) didLoadFromCCB{
//REST OF CODE
spritesLeft=3; //3 because you said there are only 3.
}
Now when you call danaldRemoved: method, just subtract 1 to spritesLeft, and check if spritesLeft is equal to 0. If it's true, just call your method to make a button appear:
- (void)danaldRemoved:(CCNode *)Danald {
spritesLeft--; //substract 1
CCParticleSystem *explosion = (CCParticleSystem *)[CCBReader load:#"Explosion"];
explosion.autoRemoveOnFinish = TRUE;
explosion.position = Danald.position;
[Danald.parent addChild:explosion];
[Danald removeFromParent];
//check if game is over.
if (spritesLeft == 0){
[self printButton];
}
}
Now create the method printButton, but before go to SpriteBuilder, create the button and place it where you want. Now uncheck 'Visible' value, and then go to code connections, and select 'Doc root var' (under custom class) and write a name for the button, for example: nextButton. At the selector value write: changeLevel and target: document root
Now declare it at the top of your .m file as you did with any other objects:
CCButton *nextButton;
Method for button (just set visibility ON)
-(void) printButton{
nextButton.visible = YES;
}
And now your method to change level:
-(void) changeLevel{
CCScene *nextLevel = [CCBReader loadAsScene:#"YOUR LEVEL"];
[[CCDirector sharedDirector] replaceScene:nextLevel];
}
Hope this helps!
EDIT: HOW TO DETECT WHEN A SPRITE GOES OFF THE SCREEN
As I said, create any kind of physic object in spritebuilder. For example, I use CCNodeColor. Then make it a rectangle and place it at left of the screen. Now go to physics, enable physics, polygon type and static. Now in connections, select doc root var and call it _leftNode. Now repeat with top,right and bottom and call them _topNode, etc.
Now go to code, declare your new nodes: CCNode *_leftNode; and so...
Now let's make a collision type:
_bottomNode.physicsBody.collisionType = #"_bound";
_leftNode.physicsBody.collisionType = #"_bound";
_rightNode.physicsBody.collisionType = #"_bound";
_topNode.physicsBody.collisionType = #"_bound";
And do the same with your sprite, but I think you have done that before. Let's make an example:
spritename.physicsBody.collisionType = #"_sprite";
So now implement the method:
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair _sprite:(CCNode *)nodeA _bound:(CCNode *)nodeB {
[_physicsNode removeChild:nodeA cleanup:YES];
}
And that's all.

Create UITextRange from NSRange

I need to find the pixel-frame for different ranges in a textview. I'm using the - (CGRect)firstRectForRange:(UITextRange *)range; to do it. However I can't find out how to actually create a UITextRange.
Basically this is what I'm looking for:
- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView {
UITextRange*range2 = [UITextRange rangeWithNSRange:range]; //DOES NOT EXIST
CGRect rect = [textView firstRectForRange:range2];
return rect;
}
Apple says one has to subclass UITextRange and UITextPosition in order to adopt the UITextInput protocol. I don't do that, but I tried anyway, following the doc's example code and passing the subclass to firstRectForRange which resulted in crashing.
If there is a easier way of adding different colored UILables to a textview, please tell me. I have tried using UIWebView with content editable set to TRUE, but I'm not fond of communicating with JS, and coloring is the only thing I need.
Thanks in advance.
You can create a text range with the method textRangeFromPosition:toPosition. This method requires two positions, so you need to compute the positions for the start and the end of your range. That is done with the method positionFromPosition:offset, which returns a position from another position and a character offset.
- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView
{
UITextPosition *beginning = textView.beginningOfDocument;
UITextPosition *start = [textView positionFromPosition:beginning offset:range.location];
UITextPosition *end = [textView positionFromPosition:start offset:range.length];
UITextRange *textRange = [textView textRangeFromPosition:start toPosition:end];
CGRect rect = [textView firstRectForRange:textRange];
return [textView convertRect:rect fromView:textView.textInputView];
}
It is a bit ridiculous that seems to be so complicated.
A simple "workaround" would be to select the range (accepts NSRange) and then read the selectedTextRange (returns UITextRange):
- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView {
textView.selectedRange = range;
UITextRange *textRange = [textView selectedTextRange];
CGRect rect = [textView firstRectForRange:textRange];
return rect;
}
This worked for me even if the textView is not first responder.
If you don't want the selection to persist, you can either reset the selectedRange:
textView.selectedRange = NSMakeRange(0, 0);
...or save the current selection and restore it afterwards
NSRange oldRange = textView.selectedRange;
// do something
// then check if the range is still valid and
textView.selectedRange = oldRange;
Swift 4 of Andrew Schreiber's answer for easy copy/paste
extension NSRange {
func toTextRange(textInput:UITextInput) -> UITextRange? {
if let rangeStart = textInput.position(from: textInput.beginningOfDocument, offset: location),
let rangeEnd = textInput.position(from: rangeStart, offset: length) {
return textInput.textRange(from: rangeStart, to: rangeEnd)
}
return nil
}
}
To the title question, here is a Swift 2 extension that creates a UITextRange from an NSRange.
The only initializer for UITextRange is a instance method on the UITextInput protocol, thus the extension also requires you pass in UITextInput such as UITextField or UITextView.
extension NSRange {
func toTextRange(textInput textInput:UITextInput) -> UITextRange? {
if let rangeStart = textInput.positionFromPosition(textInput.beginningOfDocument, offset: location),
rangeEnd = textInput.positionFromPosition(rangeStart, offset: length) {
return textInput.textRangeFromPosition(rangeStart, toPosition: rangeEnd)
}
return nil
}
}
Swift 4 of Nicolas Bachschmidt's answer as an UITextView extension using swifty Range<String.Index> instead of NSRange:
extension UITextView {
func frame(ofTextRange range: Range<String.Index>?) -> CGRect? {
guard let range = range else { return nil }
let length = range.upperBound.encodedOffset-range.lowerBound.encodedOffset
guard
let start = position(from: beginningOfDocument, offset: range.lowerBound.encodedOffset),
let end = position(from: start, offset: length),
let txtRange = textRange(from: start, to: end)
else { return nil }
let rect = self.firstRect(for: txtRange)
return self.convert(rect, to: textInputView)
}
}
Possible use:
guard let rect = textView.frame(ofTextRange: text.range(of: "awesome")) else { return }
let awesomeView = UIView()
awesomeView.frame = rect.insetBy(dx: -3.0, dy: 0)
awesomeView.layer.borderColor = UIColor.black.cgColor
awesomeView.layer.borderWidth = 1.0
awesomeView.layer.cornerRadius = 3
self.view.insertSubview(awesomeView, belowSubview: textView)
- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView {
UITextRange *textRange = [[textView _inputController] _textRangeFromNSRange:range]; // Private
CGRect rect = [textView firstRectForRange:textRange];
return rect;
}
Here is explain.
A UITextRange object represents a range of characters in a text
container; in other words, it identifies a starting index and an
ending index in string backing a text-entry object.
Classes that adopt the UITextInput protocol must create custom
UITextRange objects for representing ranges within the text managed by
the class. The starting and ending indexes of the range are
represented by UITextPosition objects. The text system uses both
UITextRange and UITextPosition objects for communicating text-layout
information. There are two reasons for using objects for text ranges
rather than primitive types such as NSRange:
Some documents contain nested elements (for example, HTML tags and
embedded objects) and you need to track both absolute position and
position in the visible text.
The WebKit framework, which the iPhone text system is based on,
requires that text indexes and offsets be represented by objects.
If you adopt the UITextInput protocol, you must create a custom
UITextRange subclass as well as a custom UITextPosition subclass.
For example like in those sources

How do I check if a CGPoint has been initialised?

I would like to initially set a CGPoint property to a particular point (middle of screen). Other methods may subsequently wish to change this property. My thoughts were to initialise it if empty in the getter, but I get the message invalid argument type 'struct CGPoint' to unary expression. I also tried using if property == nil or 0 but no joy.
Any thoughts?
-(CGPoint)graphOrigin
{
// initialise to centre of screen if has not been set
if(!_graphOrigin) // this expression is causing the problem
{
CGPoint origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width / 2, self.bounds.origin.y + self.bounds.size.height / 2);
_graphOrigin = origin;
}
return _graphOrigin;
}
A CGPoint is a struct, so you can't set it to nil or NULL (it's not a pointer). In a sense, there's really no "uninitialized" state. Perhaps you could use {0.0, 0.0} to designate an unset CGPoint, but that's also a valid coordinate. Or you could use negative x and y values to flag an "uninitialized" point, since negative values can't be valid drawing points, but that's a bit of a hack, too.
Probably your best bet is to do one of two things:
Store the property as a pointer to a CGPoint. This value can be set to NULL when uninitialized. Of course, you have to worry about mallocing and freeing the value.
Store the CGPoint alongside a BOOL called pointInitialized or somesuch, initially set to NO, but set to YES once the point has been initialized. You can even wrap that up in a struct:
struct {
CGPoint point;
BOOL initialized;
} pointData;
An easier way would be to initialize _graphOrigin to CGRectZero and change your if statement for this:
if (!CGPointEqualToPoint(_graphOrigin, CGPointZero)) {
}
CGPoint does not have an uninitialized state. However, if you consider the point (0, 0) as uninitialized, you could use
if (_graphOrigin.x == 0 && _graphOrigin.y == 0)
{
...
This works because when an Objective-C instance is initialized, all its ivar are cleared to bits of zero, which in the CGFloat representation is 0.0.
(Note: The == is fine here even if the operands are CGFloat because we want to compare with the an exact bit pattern (ignoring the issue of -0))
Since CGPointZero (0,0) and any other value you give a point may exist in your context
you may want to initialize an NSValue with your point using:
NSValue *pointVal = [NSValue valueWithCGPoint:point];
You could do this based on some condition and then later test the NSValue for nil.
NSValue can also be added to an array which would allow you to have an array of points should you need.
To get the point later simply use:
CGPoint point = [pointVal CGPointValue];
static CGPoint kInvalidPoint = {.x = NSIntegerMax, .y = NSIntegerMax};
#implementation MyClass
- init()
{
self = [super init];
if (self) {
_oldPoint = kInvalidPoint;
}
return self;
}
- (void)foo
{
if (CGPointEqualToPoint(self.oldPoint, kInvalidPoint)) {
// Invalid point.
return;
}
}
#end
Create two CGPoint properties, that way they are both "uninitialized". Set one of them and use the second one to check whether or not they are equal.
#interface ClassName ()
#property (nonatomic) CGPoint point1;
#property (nonatomic) CGPoint point2;
#end
#implementation ClassName
self.point1 = CGPointMake(69.0f, 180.0f); //arbitrary numbers
//if not equal, then if statement proceeds
if (!CGPointEqualToPoint(self.point1, self.point2) {
//your code here
}
#end
Idk if you'd consider this way hackish though. And I know your question was already answered, but I had kinda the same dilemma till I thought of this.

Method in Objective-C that points to an object

I have created a few sprites using a spriteclass and I have loaded them into an array. In my app, I loop over the array checking for particular conditions (position, etc.). I want to create an explosion method that I can pass one of these objects to and then using the pointer pull the position of the object on the screen and show an explosion there. I don't know how to pass the pointer/object that is in my array to the method to be used.
Here is essentially what I had in mind:
for (int i=1; i<4; i++) {
EnemySprite *currentenemy = [enemies objectAtIndex:i-1];
//Blow this guy up
[self explosion:currentenemy]
}
-(void)explosion someobject {
explosion.position = someobject.position
someobject.setHidden=YES;
}
You would write it like this for one param
// definition
-(void) explosion:(EnemySprite*) someObject
{
}
// usage
[self explosion: object];
For two params things are a bit more involved. Consider;
// definition
-(void) explosion:(EnemySprite*) someObject radius:(float)explosionRadius
{
...
if (pos < explosionRadius)
...
}
// usage
[self explosion: object radius:10.0f];
Everything before the : is used for the external name, everything after is the name internal to the function.
This is why you will often see Objective-C functions written with function names that end with the name of the first type:
-(void) explodeSprite:(EnemySprite*) sprite radius:(float)radius;
Both the sprite and radius params then appear to be "named" when the function is written;
[self explodeSprite:sprite radius:10.0f];
Why not make your object the receiver of the explosion?
for (id currentenemy in enemies)
{
[currentenemy explode];
}