Могу ли я передать именованную функцию в месте, где запрашивается блок?

Например, для вызова authenticateHandler

@property(nonatomic, copy) void(^authenticateHandler)(UIViewController *viewController, NSError *error)

Маленькая шляпка ^(UIViewController *viewController, NSError *error) указывает на то, что вызов должен иметь анонимный функциональный блок:

[lp setAuthenticateHandler:(^( UIViewController* vc, NSError *nsError )
  {
    if( !nsError )
    {
      puts( "GC auth success" ) ;
    }
  })];

Но скажем, я хочу, чтобы функция, которую я использую в своем вызове setAuthenticateHandler, была именованной функцией. В других местах я видел использование @selector(functionName), но здесь это не работает.


person bobobobo    schedule 29.03.2013    source источник
comment
Вам нужно будет поставить блок. Ничто не мешает вам называть свое имя внутри блока.   -  person Jeremy    schedule 29.03.2013
comment
На самом деле шаблон выглядит так: __weak YourClassName* weakSelf = self; [lp setAuthenticateHandler:(^( UIViewController* vc, NSError *nsError ) { if( !nsError ) { [weakSelf gcPlayerLoggedInSuccess];} Вам нужен указатель __weak из-за -to-a-retain-cycle">сильное захват себя в этом блоке может привести к проблеме цикла сохранения   -  person bobobobo    schedule 29.03.2013


Ответы (2)


Блоки, селекторы и указатели функций (не знаю, какой из двух последних вы называете именованными функциями) — все это несовместимые типы, поэтому вы не можете передать их там, где ожидается аргумент другого типа. К счастью, если вам нужно использовать указатели функций или селекторы с блочным API, это очень легко сделать. Блоки будут захватывать указатели функций и селекторы, которые находятся в области видимости во время их создания, и вы можете использовать их внутри блока (точно так же, как и с любой другой переменной). Например, следующий контроллер представления предоставляет оболочки для GCD (API на основе блоков), которые принимают селекторы или указатели функций в качестве аргументов:

ViewController.h:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end

ViewController.m:

#import "ViewController.h"

void callback() { NSLog(@"call back function"); }

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self doSomethingWithCompletionSelector:@selector(callback)];
//    [self doSomethingWithCompletionFunction:callback];

}

- (void)callback
{
    NSLog(@"call back selector");
}

- (void)doSomethingWithCompletionSelector:(SEL)selector
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {
        NSLog(@"Doing something");
        // Causes a warning in ARC
        [self performSelector:selector];
    });
}

- (void)doSomethingWithCompletionFunction:(void (*)())function
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Doing something");
        function();
    });
}

@end

И, конечно же, вы можете явно вызвать любой метод или функцию, и получатель и аргументы будут захвачены блоком.

person Carl Veazey    schedule 29.03.2013

Селекторы и блоки — совершенно разные понятия.

@selector(functionName) относится к типу SEL

block — это синтаксическая функция среды выполнения уровня C, а в Objective-C это фактически объект.

Для получения дополнительной информации о селекторах проверьте здесь.

Дополнительную информацию о блоках см. здесь.

person Pedro Mancheno    schedule 29.03.2013