Allen
Allen

Reputation: 3771

Carrying custom properties over delegate methods

I am currently pulling a list of "contest" objects that have location information tied to them. I want to monitor all contests that I am in the vicinity of.

       for(Contest *contest in contests) {

            NSMutableDictionary * fence1 = [NSMutableDictionary new];
            [fence1 setValue:contest.event.name forKey:@"identifier"];
            [fence1 setValue:[NSString stringWithFormat:@"%f", contest.location.latitude] forKey:@"latitude"];
            [fence1 setValue:[NSString stringWithFormat:@"%f", contest.location.longitude] forKey:@"longitude"];
            [fence1 setValue:@"1000" forKey:@"radius"];

            //the below method returns a CLRegion object
            CLRegion *region = [self dictToRegion:fence1];

            //adding custom contest object to region
            region.contest = contest;

            [self.locationManager requestStateForRegion:region];
        }

I ALSO want to tie a custom contest property to the region (as shown in the above code), but it doesn't seem to carry over in the delegate method didDetermineState:

-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
switch (state) {
    case CLRegionStateUnknown:
        NSLog(@"Unknown state!");
        break;

    case CLRegionStateInside:
        NSLog(@"Inside state!");

        //this comes back as null
        NSLog(@"%@", region.contest.name);

        break;

    case CLRegionStateOutside:
        NSLog(@"Outside state!");
        break;

    default:
        break;
}
}

In the delegate method, region.contest returns as (null). Is there a better approach to take?

Appendix (my category for CLRegion): CLRegion+Contest.h:

#import <CoreLocation/CoreLocation.h>
#import "Event.h"
#import "Contest.h"

@interface CLRegion (Loopd)

@property (nonatomic, strong) Event *event;
@property (nonatomic, strong) Contest *contest;

@end

CLRegion+Contest.m:

#import "CLRegion+Loopd.h"
#import <objc/runtime.h>

static char defaultHashKey;

@implementation CLRegion (Loopd)

@dynamic event;
@dynamic contest;

-(Event* ) event {
    return objc_getAssociatedObject(self, &defaultHashKey);
}

- (void) setEvent:(Event *)event {
    objc_setAssociatedObject(self, &defaultHashKey, event, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(Contest* ) contest {
    return objc_getAssociatedObject(self, &defaultHashKey);
}

- (void) setContest:(Contest *)event {
    objc_setAssociatedObject(self, &defaultHashKey, event, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}


@end

Upvotes: 0

Views: 87

Answers (1)

blazejmar
blazejmar

Reputation: 1090

There are 2 problems with your category. 1. You're using same key for both properties. 2. defaultHashKey is initialized with 0 value.

objc_getAssociatedObject and objc_setAssociatedObject work mostly like setValue:forKey: and getValueForKey:. So you need to provide key which binds the value to the object. Try something like that:

#import "CLRegion+Loopd.h"
#import <objc/runtime.h>

static char* kEventKey = "kEventKey";
static char* kContestKey = "kContestKey";

@implementation CLRegion (Loopd)

@dynamic event;
@dynamic contest;

-(Event* ) event {
    return objc_getAssociatedObject(self, kEventKey);
}

- (void) setEvent:(Event *)event {
    objc_setAssociatedObject(kEventKey, event, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(Contest* ) contest {
    return objc_getAssociatedObject(self, kContestKey);
}

- (void) setContest:(Contest *)event {
    objc_setAssociatedObject(self, kContestKey, event, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

This code should work, but would be much better to create separate object for storing this association (I'm not a great fan of using runtime for this kind of purposes).

EDIT: Your assigning value for contest multiple times in the for loop. So one of the contests (the last one) is assigned to the CLRegion object.

Upvotes: 1

Related Questions