Добавление контекста в элемент управления пользовательского интерфейса или NSObject

Здорово иметь возможность addTarget на UIButton. Я только хотел бы, чтобы был какой-то хитрый способ, которым я мог бы прикрепить состояние к UIButton, чтобы при вызове целевого метода я мог волшебным образом получить это состояние (любой идентификатор) от отправителя.

Что-то типа:

[button shoveMyObjectInThere:foo];
[button addTarget:self action:@selector(touchyTouchy:) forControlEvents:UIControlEventTouchUpInside];

С последующим:

-(void) touchyTouchy:(id) sender {
    UIButton button = (UIButton*)sender;
    id foo = [button getByObjectBack];
    // do something interesting with foo
}

Было бы здорово, если бы у UIButton было свойство 'id context', куда разработчики могли бы добавлять разные вещи, но, похоже, это не так. Однако Objective-C — очень динамичный язык, поэтому мне интересно, есть ли какой-то хитрый способ добавить метод или поля к объекту во время выполнения?


person David Blevins    schedule 06.01.2011    source источник
comment
Ничего себе, я LOLed, когда я увидел это имя селектора!!! :)   -  person Jacob Relkin    schedule 06.01.2011


Ответы (4)


Вы можете попробовать сделать ассоциативную ссылку

#import <objc/runtime.h>

objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy); 
objc_getAssociatedObject(id object, void *key);
person Rich    schedule 10.01.2011
comment
Это потрясающе! Большое спасибо! - person David Blevins; 11.01.2011

Как насчет чего-то вроде setValue:forKey:, часть функции кодирования Key-Value в Objective-C?

person fbrereto    schedule 06.01.2011
comment
Дал это вращение, и документы, и мои эксперименты, похоже, указывают, что это только для установки существующих полей/аксессоров. - person David Blevins; 06.01.2011
comment
Не представляется возможным добавить данные о новых участниках с помощью KVC. См. раздел Почему мой объект не соответствует кодированию значения ключа? - person Skotch; 31.05.2013

Так что я просто сделал быстрый тест и нашел некоторые интересные результаты.

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:@"Hello" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(100, 100, 100, 100);
[self.window addSubview:button];

// ...

- (void)buttonClicked:(id)sender {
    NSLog(@"button clicked %@", [sender class]);
}

Это печатает: button clicked UIRoundedRectButton

Так что кажется, что это должно быть возможно... По правде говоря, я столкнулся с некоторыми проблемами при создании подкласса UIButton, чтобы заставить работать полный пример, но это кажется многообещающим. :)

person donkim    schedule 06.01.2011
comment
Этот ответ, похоже, не связан с вопросом. Вы не добавили никакого контекста в UIButton, который можно вытащить в buttonClicked: - person Skotch; 31.05.2013

Официальное решение — использовать свойство «тег»:

[self.someMutableArray addObject:foo];
button.tag = self.someMutableArray.count - 1;

[button addTarget:self action:@selector(touchyTouchy:) forControlEvents:UIControlEventTouchUpInside];

Потом:

-(void) touchyTouchy:(id) sender {
    UIButton button = (UIButton*)sender;
    id foo = self.someMutableArray[button.tag];
    // do something interesting with foo
}

В большинстве ситуаций вы бы использовали enum или константу для тега, но массив, очевидно, более гибкий.

person Abhi Beckert    schedule 06.12.2017