Возможно ли превратить обратный вызов в асинхронный блок? - PullRequest
5 голосов
/ 25 февраля 2012

Я использую API-интерфейс dropbox для моего нового проекта . API основан на делегатах и ​​колбэках, в парах (успех + сбой), например:

- (void)restClient:(DBRestClient*)client loadedMetadata:(DBMetadata*)metadata;
- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error; 

- (void)restClient:(DBRestClient*)client loadedAccountInfo:(DBAccountInfo*)info;
- (void)restClient:(DBRestClient*)client loadAccountInfoFailedWithError:(NSError*)error; 

Интересно, существует ли способ превратить это в асинхронный блок obj-c, чтобы я мог сделать это:

+ (void)loadMetadata:(DBRestClient *)client queue:(NSOperationQueue *)queue completionHandler:(void (^)(DBMetadata*, NSError*))handler

Существует какой-то шаблон, который можно использовать для этого? Или необходимо, чтобы библиотека с самого начала собиралась из блоков?

Ответы [ 2 ]

7 голосов
/ 17 октября 2012

В настоящее время существует библиотека с открытым исходным кодом DropBlocks, которая предоставляет блочные версии всех функций Dropbox iOS SDK.

https://github.com/natep/DropBlocks

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

2 голосов
/ 25 февраля 2012

Вы можете сделать вспомогательную функцию для этого:

-(void) loadMetadataOnQueue:(NSOperationQueue *) queue completion:(void (^)(DBMetadata*, NSError*))handler
{
    // assuming this is a category on DBRestClient
    AsyncDelegate *delegate = [AsyncDelegate new];
    delegate.metadataBlock = handler;
    self.delegate = delegate;

    [self loadMetadata:queue];
}

@interface AsyncDelegate

@property(readwrite, copy) void (^metadataBlock)(DBMetadata*, NSError*);

@end

@implementation AsyncDelegate

@synthesize metadataBlock;

-(void)restClient:(DBRestClient*)client loadedMetadata:(DBMetadata*)metadata
{
    metadataBlock(metadata, nil);
}

- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error
{
    metadataBlock(nil, error);
}

end
...