Функция, която връща функция

Как да присвоите и впоследствие да извикате функция, която връща функция към локална променлива в Objective-C?

АКТУАЛИЗАЦИЯ:

Измислих следното, но все още не е правилно, страхувам се:

(void (^)()) (^loadedCallback) () = (void (^)()) ^(){
    @synchronized (synchronizer) {
        semaphore++;
    }
      return Block_copy(^{
          @synchronized (synchronizer) {
              semaphore--;
              if (semaphore == 0) {
                  onAllLoaded();
              }
          }
      }); };

person mgamer    schedule 13.07.2011    source източник
comment
Може да искате да разгледате dispatch_semaphores, които осигуряват бърз интерфейс без заключване към семафори.   -  person zneak    schedule 13.07.2011


Отговори (1)


Първо, трябва да разберете синтаксиса за деклариране на указател на функция. Същото е и за блоковете, с изключение на това, че е ^ вместо *.

След това трябва да създадете блок и да върнете негово копие и да го присвоите на правилно декларирана променлива.

typedef NSArray* (^my_block_type_t)(int, float);

my_block_type_t createBlock()
{
    my_block_type_t block = ^(int a, float b)
    {
        return [NSArray array];
    };
    return Block_copy(block);
}

/* snip */
my_block_type_t theBlock = createBlock();
theBlock();
Block_release(theBlock);

РЕДАКТИРАНЕ за справяне с редакцията на OP: typedefs обикновено се използват, за да направят кода по-лесен за четене. В случай на блокове и функционални указатели, това също улеснява писането. Има вграден typedef (dispatch_block_t) за блокове, които не приемат аргументи и връщат void; трябва да го използвате. Трябва също така да направите толкова дефиниции на типа, колкото са ви необходими, за да избегнете използването на грозните функционални указатели на синтаксиса на декларацията, които в противен случай се налагат върху вашия код.

typedef dispatch_block_t (^block_creator_t)();

block_creator_t loadedCallback = ^{
    @synchronized (synchronizer)
    {
        semaphore++;
    }

    dispatch_block_t result = ^{
        @synchronized (synchronizer)
        {
            semaphore--;
            if (semaphore == 0)
                onAllLoaded();
        }
    };

    return Block_copy(result);
};
person zneak    schedule 13.07.2011
comment
Не трябва ли да се използват Block_copy и Block_release? Знам, че блоковете имат isa указател и могат да бъдат изпратени съобщения, просто изглежда, че това е детайл от изпълнението. - person Joe; 13.07.2011
comment
@Joe, това е най-вече (лош?) навик от моя страна. Ще променя това на Block_copy/Block_release. - person zneak; 13.07.2011