2015-08-28 3 views
0

Я использую фреймворк, который использует огромное количество аргументов блока для испускания событий. Из-за лицензирования я не могу выпустить образцы кода, но я все еще могу получить свой код с похожим кодом. Допустим, у вас есть следующий код:Метод литья в Objective C

- (void)begin 
{ 
    [MyService doSomething:^{ 
     NSLog(@"Done."); 
    }]; 
} 

Это прекрасно, но методы, которые я имею дело есть 14 блоков аргументы, большинство из которых принимают несколько параметров, так что это делает его очень трудно читать и трудно проверить без создания повторяющегося кода котельной.

Есть ли способ, я могу указать блок для метода данных экземпляра, что-то вроде:

- (void)doSomethingDelegate 
{ 
    NSLog(@"Done."); 
} 

- (void)begin 
{ 
    [MyService doSomething:CALLBACK(self, @selector(doSomethingDelegate))]; 
} 

Где CALLBACK макроса или родная конструкция. Это возможно?

+0

Вы смотрели в использовании [NSInvocation] (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/)? – Tim

+2

Вы можете просто вызвать метод из каждого из блоков. Весь «уродливый» код будет в одном месте, и вы можете разделить логику на части. – titaniumdecoy

+1

Почему бы не использовать методы, возвращающие блоки? – vikingosegundo

ответ

2

Нет, но вы можете объявить локальные блоки:

- (void)begin 
{ 
    void (^callback)() = ^{ NSLog(@"Done."); }; 

    [MyService doSomething:callback]; 
} 

Вы можете расширить, что:

- (void)callbackImpl { 
    NSLog(@"Done."); 
} 

- (void)begin { 
    void (^callback)() = ^() { [self callbackImpl]; }; 

    [MyService doSomething:callback]; 
} 

И вы можете представить себе макрос сорта:

#define CALLBACK(name) void (^name)() = ^{ [self name##Impl]; }; 

Это становится немного грязнее, когда у вас есть аргументы в блоке, и вам нужно подумать, хотите ли вы сильную или слабую ссылку на себя в этих блоках ...

+0

Первый пример кода - это то, что я делаю сейчас, но у него все еще есть главный недостаток, из-за которого я не могу издеваться над обратными вызовами, чтобы проверить, если их стрельба. Второй пример кода - это то, что я чувствовал, что я был вынужден делать, но это огромное количество кода котла, которого я хочу избежать. –

+0

Я бы предпочел, чтобы язык (тип безопасного) кастинг, но макрос всегда будет резервным решением. Я удивлен, что это не позволяет это ... –

+1

Ну, вызов блока и селектора - это две разные вещи. Я не говорю, что это было бы невозможно ... но я не удивлен, что это не язык. По-видимому, это особенность Swift, по мнению других комментаторов, поэтому, возможно, в этом направлении лежит ваше решение. –

0

Так как я должен беспокоиться об аргументах, которые в ином от этого является лучшим решением я нашел до сих пор:

#define wrapper(args, method) ^args { [self method]; } 

- (void)onUpdatingDeviceWithMessage:(NSString *)message progress:(float)progress 
{ 
} 

- (void)begin 
{ 
    [MyService ... 
     onUpdatingDevice:wrapper((NSString *message, float progress), 
           onUpdatingDeviceWithMessage:message progress:progress) 
} 
Смежные вопросы