2012-07-03 3 views
3

Я создаю barButton, который при нажатии должен установить режим редактирования UITableView на «да». Вот мой код:Выполнение кода блока на месте @selector

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: @"Edit" 
                      style: self.navigationController.navigationItem.leftBarButtonItem.style 
                      target: self 
                      action: ]; 

То, что я не понимаю, что мне нужно поставить в качестве аргумента для action части так, что я могу выполнить блок кода там. Я мог бы легко разместить @selector(someMethod), но я выполняю только одну или две строки, и создание другого метода довольно бессмысленно.

Спасибо за помощь!

ответ

7

Далее на комментарий ПГБ, написав что-то вроде этого будет решить эту проблему:

@interface PJBlockHolder 

+ (id)blockHolderWithBlock:(dispatch_block_t)block; 
- (void)invoke; 

@end 

/* obvious implementation; copy the block, issue it upon invoke */ 

И:

[[UIBarButtonItem alloc] initWithTitle: @"Edit" 
    style: self.navigationController.navigationItem.leftBarButtonItem.style 
    target: [PJBlockHolderWithBlock:^{ /* your code here */ }] 
    action:@selector(invoke) ]; 

Итак, вы создали пользовательский объект, который оборачивает блок и выдает его на конкретный селектор.

EDIT: как указано ниже, UIControl s не сохраняют свои цели. Поэтому, вероятно, самая простая задача - связать время жизни держателя блока с временем жизни элемента управления; это не обязательно идеально, потому что тогда держатель переживет свою полезность, если впоследствии вы удалите его как цель, сохранив контроль, но он, вероятно, подходит для большинства случаев.

Варианты либо использовать Objective-C встроенный в связанных с ними объектов, или использовать тот факт, что UIControl унаследован от UIView, придавая ему CALayer, который может хранить произвольные объекты по ключу.

Justin Spahr-Summers ссылки на хорошо документированную реализацию публичного права первого в его комментарии ниже, поэтому я покажу пример последнего, даже если он взломан для обсуждения.

PJBlockHolderWithBlock *blockHolder = [PJBlockHolderWithBlock:^{ /* your code here */ }]; 
UIBarButtonItem *barButtonItem = 
    [[UIBarButtonItem alloc] initWithTitle: @"Edit" 
     style: self.navigationController.navigationItem.leftBarButtonItem.style 
     target: blockHolder 
     action:@selector(invoke) ]; 
[barButtonItem.layer setValue:blockHolder forKey:@"__myBlockHolderKey__"]; 
+1

Это вводит некоторые сложности управления памятью. Тем не менее, у меня есть [реализация общедоступного домена] (https://github.com/jspahrsummers/libextobjc/blob/master/extobjc/EXTBlockTarget.h) чего-то подобного. –

+2

@ JustinSpahr-Summers вы правы; Я, конечно, забыл вспомнить, что 'UIControl' не сохраняют свои цели, что было глупо, потому что это, очевидно, вызовет петли сохранения. Решение 'objc_setAssociatedObject' - это именно то, что я сделал бы сам. – Tommy

+0

Спасибо за помощь, но похоже, что это намного сложнее, чем я ожидал, я, вероятно, просто позвоню методу хаха! – prince

2

Вы не можете сделать это так, как планируете. Параметры target:action: предназначены для отправки объекта и селектора для вызова этого объекта. Насколько я знаю, нет эквивалентного API, который использует блоки.

Смежные вопросы