Как использовать performSelector:withObject:afterDelay: на методе с несколькими аргументами

выберите *, обычно делает для плохого кода, поскольку новые столбцы имеют тенденцию быть добавленными или порядок изменения столбцов в таблицах вполне часто, которое обычно повреждает выбор * в очень тонкие пути. Так список столбцы является правильным решением.

относительно того, как сделать Ваш запрос, не уверенный в mysql, но в sqlserver, Вы могли выбрать имена столбцов из syscolumns и динамично создать избранный пункт.

5
задан Mike Abdullah 18 October 2009 в 12:15
поделиться

4 ответа

Несколько недель назад я ответил на довольно похожий вопрос. Ответ на этот вопрос отредактирован ниже.

В общем, я избегаю NSInvocation для такого рода работ. Обычно это вызывает головную боль при обслуживании и, в частности, создает трудности при рефакторинге в будущем.

Во-первых, учитывая этот метод:

 -(void)plotPoly:(Polygon *)poly WithColor:(UIColor *)color AndFill:(BOOL)filled;

Обычно его объявляют как:

 -(void)plotPoly:(Polygon *)aPoly color:(UIColor *)aColor filled:(BOOL)filledFlag;

Это немного больше соответствует соглашению об именах.

Теперь я бы фактически записал аргументы в простой класс, который предоставляет метод -invoke .

Что-то с таким интерфейсом:

PolyPlotter.h:

@interface  PolyPlotter : NSObject
{
    Polygon *poly;
    UIColor *color;
    BOOL filled;
}

+ plotterWithPoly: (Polygon *) aPoly color: (UIColor *) aColor filled: (BOOL) filledFlag; 

- (void) plot;
@end

PolyPlotter.m:

@interface PolyPlotter()
@property Polygon *poly;
@property UIColor *color;
@property BOOL filled;
@end

@implementation PolyPlotter
@synthesize poly, color, filled;

+ plotterWithPoly: (Polygon *) aPoly color: (UIColor *) aColor filled: (BOOL) filledFlag; 
{
    PolyPlotter *polygonPlotter = [PolyPlotter new];
    polygonPlotter.poly = aPoly;
    polygonPlotter.color = aColor;
    polygonPlotter.filled = filledFlag;
    return [polygonPlotter autorelease];
}

- (void) plot;
{
    // ... do your plotting here ...
}
@end

Использовать просто. Просто создайте экземпляр PolygonPlotter и скажите ему выполнить селектор plot после задержки или в основном потоке или что-то еще.

Учитывая вопрос, Я подозреваю, что вам может понадобиться немного больше контекста во время рисования? Если это так, вы можете передать эту информацию в качестве аргумента в -plot , например, объявив метод как:

- (void) plot: (UIView *) aViewToPlotIn;

Или что-то в этом роде.

Как я уже сказал, немного больше кода, но намного более гибкий и реорганизуемый, чем шаблон NSInvocation. Например, вы можете легко сделать из PolygonPlotter что-нибудь, что можно будет заархивировать.

7
ответ дан 18 December 2019 в 07:55
поделиться

Все еще не совсем то, что я бы назвал элегантным, но менее неприятным, чем необходимость изменения всего API, - это NSInvocation:

Polygon *poly;
UIColor *color;
BOOL filled;
// Assume the above variables exist
NSInvocation *inv = [NSInvocation invocationWithMessageSignature:[target messageSignatureForSelector:message]];
[inv setArgument:&poly atIndex:2];
[inv setArgument:&color atIndex:3];
[inv setArgument:&filled atIndex:4];
[inv performSelector:@selector(invokeWithTarget:) withObject:target afterDelay:1];

Другой лучший вариант - просто создать метод-оболочку, который вызывает исходный с соответствующими аргументами (возможно, в виде словаря или массива), который соответствует сигнатуре, необходимой для выполнения после задержки.

9
ответ дан 18 December 2019 в 07:55
поделиться

Библиотека Three20 Джо Хьюитта содержит несколько расширенных версий performSelector, которые могут оказаться полезными (я публикую только фрагмент):

- (id)performSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3 {
  NSMethodSignature *sig = [self methodSignatureForSelector:selector];
  if (sig) {
    NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
    [invo setTarget:self];
    [invo setSelector:selector];
    [invo setArgument:&p1 atIndex:2];
    [invo setArgument:&p2 atIndex:3];
    [invo setArgument:&p3 atIndex:4];
    [invo invoke];
    if (sig.methodReturnLength) {
      id anObject;
      [invo getReturnValue:&anObject];
      return anObject;
    } else {
      return nil;
    }
  } else {
    return nil;
  }
}

Просто добавьте их в категорию NSObject .

4
ответ дан 18 December 2019 в 07:55
поделиться

Я считаю, что NSArray - разумное решение, и да, это означало бы изменение сигнатуры метода на использование NSArray * в качестве единственного аргумента.

0
ответ дан 18 December 2019 в 07:55
поделиться