简体   繁体   中英

Objective-C callback changing Parameter Values

So I am trying to get a callback setup in Objective-C. I am use to C++ so I keep hitting this stuff the wrong way. I found this answer and have been trying to model my code in the same way.

How to perform Callbacks in Objective-C

However when in my 'LocationActivated' function the xCoord and yCoord seem to have the complete wrong values.

delegate.mm

- (void)Initialize {
    [mWorldObj RegisterActivateDelegate: self];
}

-(void) LocationActivated :(float)xCoord :(float)yCoord {

    int a;
    a++;
    pLocation.center = CGPointMake(xCoord, yCoord);
}

delegate.h

-(void) LocationActivated :(float)xCoord :(float)yCoord;

world.h

id mActivateDelegate;

Delegate call in world.mm

        float msgarr[2];
        msgarr[0] = (float)((camera.VideoWidth() * 0.5f) + projX) + curLoc->mPopOffsetX;
        msgarr[1] = (float)((camera.VideoHeight() * 0.5f) - projY) + curLoc->mPopOffsetY;
        if(mActivateDelegate != null) {

            [mActivateDelegate LocationActivated :msgarr[0] :msgarr[1]];
        }

When calling msgarg[0] and [1] are completely valid values, ~(200, 200). But when in the callback the values are now completely different. I dumped the memory on both sides and didn't see any commonalities so my best guess is I am doing the function call totally wrong.

I also get a warning on the [mActivateDelegate LocationActivated] line saying 'Location Activated may not repsond' which makes sense because as far as the compiler knows mActiveDelegate is of type 'id'.

Any idea what I am doing wrong? Better way to approach this?

Edit:

Adding Register function from delegate.mm

- (void)RegisterActivateDelegate :(id) delegate {

    mActivateDelegate = delegate;
}

You asked for a better way to do it. I typed this directly into the window, so I don't know if it compiles, but this is how to approach it. Name things using ObjC conventions. This is important and will break things if you don't. Methods start with a lower-case. Name your parameters.

World.h

@protocol WorldDelegate;
@interface World : NSObject
@property (nonatomic, readwrite, assign) id<WorldDelegate> delegate;
@end

@protocol WorldDelegate <NSObject>
- (void)world:(World*)world didActivateLocation:(CGPoint)aPoint;
@end

World.mm

@implementation World
@synthesize delegate = delegate_;

- (void)dealloc {
    delegate_ = nil;
    [super dealloc];
}

...

if ([self delegate] != nil) {
    CGFloat x = ((camera.VideoWidth() * 0.5f) + projX) + curLoc->mPopOffsetX;
    CGFloat y = ((camera.VideoHeight() * 0.5f) - projY) + curLoc->mPopOffsetY;
    [[self delegate] world:self didActivateLocation:CGPointMake(x, y)];
}

WorldDelegate.h

#import "World.h"
@interface WorldDelegate : NSObject <WorldDelegate>
@property (nonatomic, readwrite, assign) World *world;
- (id)initWithWorld:(World*)aWorld;
@end

WordDelegate.mm

@interface WorldDelegate
@synthesize world = world_;
- (id)initWithWorld:(World*)aWorld {
    self = [super init];
    [aWorld setDelegate:self];
    world_ = aWorld;
    return self;
}

- (void)dealloc {
    [world_ setDelegate:nil];
    world_ = nil;
    [super dealloc];
}

- (void)world:(World*)aWorld didActivateLocation:(CGPoint)aPoint {
    int a;    // What is all this?
    a++;
    pLocation.center = aPoint;
}

Edit Well, it turns out I don't actually know the answer. I thought Objective-C methods required named parameters, but in fact your method signature is valid. However, you should make your method names as descriptive as possible.

You should give your parameters names. For example, your delegate method should look like this:

- (void)locationActivatedWithX:(float)xCoord andY:(float)yCoord;

Although it's not 100% crucial , it's good style.

One issue - DON'T CHECK for == NULL. Check for == nil. Objective-C objects must be checked against "nil" meaning that yes they're a valid object but they don't reference anything. Your delegate object exists, and as an objective-c type object it has some information (like retain counts, isa pointer, etc) so it won't necessarily be NULL, but could still be nil as in not actually referencing a real object.

Also, if things are right, you won't get that warning message "'Location Activated may not repsond' ".. the compiler is smart enough to suppress those warnings on an id type, IF the method declaration does exist in an interface that you're including. Since you get the warning, that sounds fishy - like it either isn't seeing your interface declaration or what you have in that .h isn't quite right.

What does your RegisterActiveDelegate method look like? You say you did a memory dump, so the method you want truly is being called it sounds like.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM