Перенос пользовательских свойств поверх методов делегирования

#ios #delegates

#iOS #делегаты

Вопрос:

В настоящее время я извлекаю список объектов «contest», к которым привязана информация о местоположении. Я хочу следить за всеми соревнованиями, на которых я нахожусь поблизости.

        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];
        }
 

Я ТАКЖЕ хочу привязать пользовательское свойство contest к региону (как показано в приведенном выше коде), но, похоже, оно не переносится в метод делегирования 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;
}
}
 

В методе делегирования region.contest возвращает значение (null). Есть ли лучший подход, который можно использовать?

Приложение (моя категория для 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
 

Регион Конкурс.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, amp;defaultHashKey);
}

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

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

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


@end
 

Ответ №1:

С вашей категорией есть 2 проблемы. 1. Вы используете один и тот же ключ для обоих свойств. 2. defaultHashKey инициализируется значением 0.

objc_getAssociatedObject и objc_setAssociatedObject работают в основном как setValue:forKey: и getValueForKey: . Итак, вам нужно предоставить ключ, который привязывает значение к объекту. Попробуйте что-то подобное:

 #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
 

Этот код должен работать, но было бы намного лучше создать отдельный объект для хранения этой ассоциации (я не большой поклонник использования среды выполнения для такого рода целей).

РЕДАКТИРОВАТЬ: вы присваиваете значение для конкурса несколько раз в цикле for. Итак, один из конкурсов (последний) присваивается объекту CLRegion.

Комментарии:

1. так это вообще плохой метод? кстати, я все еще получаю null для связанного объекта.

2. Я подтвердил, что настройка / получение работает с вашим кодом, но в вызываемом методе делегирования объект contest больше не связан с объектом region, возвращенным методом делегирования

3. Я понял, что метод делегирования не возвращает то же самое object…so кажется, нет хорошего способа обойти эту проблему!

4. Это неплохо, если вы на 100% уверены в том, что делаете, и каковы недостатки. Что также может быть неправильным в вашем коде, так это то, что вы присваиваете значение объекта несколько раз. См. Редактирование в моем сообщении.