Мога ли да предам функция с име на място, където се иска блок?

Например, за да извикате 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 ptr поради улавянето на себе си силно в този блок вероятно ще доведе до проблем с цикъл на задържане   -  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