Получение аргументов метода objective-c по индексу

#objective-c #c

#objective-c #c

Вопрос:

Я знаю, что методы objective-c на самом деле являются функцией c, и что первыми двумя аргументами являются self и _cmd. Я пытаюсь получить остальные аргументы в виде массива (включая или исключая self и _cmd)

Например:

 -(void)someMethod:(id)firstArg withObject:(id)secondArg andObject:(id)thirdArg {
     //then something like:
     args[0] //corresponds to self
     args[1] //corresponds to _cmd
     args[2] //corresponds to firstArg
     args[3] //corresponds to secondArg
     args[3] //corresponds to thirdArg
     //or just start from firstArg being the 0th item in the index (skipping out self and _cmd)
}
  

То, что я пытаюсь сделать, это что-то вроде:

 [self doOtherMethod:@selector(otherMethod:withObject:andObject:) withObjects:args];
  

Итак, как я могу получить массив (c array или даже NSArray) аргументов, переданных методу, чтобы я мог передавать их или перечислять через них?

РЕДАКТИРОВАТЬ: я хочу сделать это с помощью существующих методов, например, методов делегирования, которые я не могу изменить.

Комментарии:

1. Возможно, вы можете сделать это с помощью блоков ObjC.

2. На самом деле это невероятно сложная проблема.

3. @DaveDeLong, если ты так говоришь, то для меня это невозможно 😉

4. @Jonathan. да, получение NSInvocation для текущего вызова метода возможно , но потребует много работы.

5. @DaveDeLong, мне сейчас просто любопытно, я не думаю, что где-нибудь я могу узнать больше об этом?

Ответ №1:

Используйте NSInvocation; он может инкапсулировать почти произвольный набор аргументов, селектор и цель, которые затем могут быть вызваны позже простым способом.

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

То, что вы пытаетесь сделать, обычно указывает на проблемы с дизайном / архитектурой. Вам не нужно этого делать.

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


но может ли он также получить доступ к аргументам текущего метода?

«Вроде того».

Непонятно, о чем вы спрашиваете. Если «текущий метод» не является тем, который вы реализовали, то вы мало что можете сделать (за исключением swizzling или других игр во время выполнения, которые действительно никогда не должны использоваться).

Если это тот, который вы реализовали, просто используйте аргументы. Вы можете закодировать их в NSInvocation, если хотите отложить выполнение (или блок).

NSInvocation используется для сбора аргументов в конкретном случае; в частности, при реализации пересылки метода. Но это, похоже, не связано с тем, что вы пытаетесь сделать.

Комментарии:

1. Я знаю, что NSInvocation можно использовать для отправки сообщения ( / вызова метода), но может ли он также получить доступ к аргументам текущего метода?

Ответ №2:

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

Вот статья, которая, я думаю, станет отличной отправной точкой для получения более глубокого понимания того, как передаются аргументы: http://en.wikipedia.org/wiki/Calling_convention

Ответ №3:

Попробуйте создать функцию, которая принимает в NSArray эти аргументы. Вы можете сделать это, не передавая в self или _cmd.

 - (void)serverRespondedWithJSONObjects:(NSArray *)objects {
  NSMutableArray *objects = [NSMutableArray array];
  for (NSDictionary *dictonary in objects) {
    SomeObject *object = [[[SomeObject alloc] init] autorelease];
    object.name = [dictionary valueForKey:@"name"];
    [objects addObject:object];
  }
  [self doSomethingWithArgs:objects];
}

- (void)doSomethingWithArgs:(NSArray *)args {

  for (SomeClass *someObject in args) {
    //do something interesting with someObject.
  }

}
  

Комментарии:

1. Извините, но я хочу сделать это с помощью существующих методов, а не создавать новые.