2013-03-06 2 views
2

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

[anObject performSelector:@selector(thisMethod:) withObject:passedObject]; 

эквивалентно:

[anObject thisMethod:passedObject]; 

Пожалуйста, скажите мне, что это differnce с точки зрения компиляции, памяти и т. д.

+1

Последний более гибкий, поскольку он позволяет вам поставлять более двух параметров (выполнитьSelector: withObject: withObject :). – Till

+2

Но мы можем передать десятки объектов, упакованных в массив, как 1 параметр. –

+1

@AnoopVaidya yikes, DONT. Для таких сценариев используется «NSInvocation». – Till

ответ

7

Семейство методов performSelector предназначено для особых случаев, подавляющее большинство вызовов методов в Obj-C должно быть прямым. Некоторые отличия:

Непрямой: При использовании метода performSelector для вызова метода у вас есть два метода вызова; значение performSelector и целевой метод.

Аргументы являются объектами: При вызове через performSelector все аргументы должны передаваться как объекты, например. при вызове метода, который принимает значение double, тогда это значение должно быть обернуто как NSNumber перед передачей performSelector. Методы performSelector разворачивают необязательные аргументы перед вызовом целевого метода. При прямом вызове не требуется упаковка или разворачивание.

только два аргумента:performSelector семейство включает в себя только варианты, которые проходят 0, 1 или 2 аргумента, так что вы не можете использовать их, чтобы вызвать метод, который принимает 3 или более аргументов.

Вероятно, вы видите большинство из вышеперечисленных как негативы, так в чем преимущества?

Динамического селектор:performSelector семьи позволяет вызывать метод, который не известен до момента выполнения, только его типа должен быть известен (так что вы можете передать правильные аргументы и получить правильный результат); другими словами, аргументом селектора может быть выражение типа SEL. Это можно использовать, если вы хотите передать метод в качестве аргумента другому методу и вызвать его. Однако, если вы компилируете ARC с помощью динамических селекторов, является нетривиальным и обычно выдает предупреждения компилятора, так как, не зная, что селектор ARC не может знать атрибуты собственности аргументов.

Отложенное исполнение: Семейство performSelector включает методы, которые вызывают метод после задержки.

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

0

Если ваше приложение хочет использовать reflection, где, изменяя некоторые значения в файле конфигурации, вы хотите вызвать differe nt (различные адаптеры). Или в зависимости от типа объекта вы хотите вызвать другой метод во время выполнения.

Если вы разрабатываете настраиваемый продукт, это мощная функция.

+1

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

+0

Это всегда есть, это компромисс между легкостью развития и расширяемости. – Anupdas

1

Метод performSelector: позволяет отправлять сообщения, которые не определены до времени исполнения. Для получения дополнительной информации читайте this.

-1

Мне нравится использовать [id performSelecter: selector withObject] при объявлении и реализации настраиваемого протокола, а также делегировать шаблон, а также пример использования, где мы должны использовать функцию performselector вместо прямого вызова метода. ..

+0

'performSelector:' не должен использоваться с протоколами или делегатами. У вас есть объявление метода в обоих случаях, поэтому селектор известен и может быть вызван напрямую. – bbum

2

performSelector:withObject: будет немного медленнее, чем вызов метода напрямую. Косвенное обозначение также означает, что компилятор не может выполнить правильную проверку типов. С включенным ARC вы также столкнетесь с проблемами, в которых компилятор будет жаловаться, потому что невозможно точно определить, что такое политика управления памятью.

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

Такой динамизм необходим только тогда, когда имя селектора - имя метода - не может быть определено во время компиляции. Он не должен использоваться для методов @optional в протоколах и не должен использоваться во время делегирования (в обоих случаях respondsToSelector: + прямой вызов метода - гораздо лучший шаблон для использования).

+0

Из любопытства я просто подавлял это предупреждение, но есть ли какие-либо последствия ARC, которые я должен принимать во внимание? Я не думаю, что методы возвращают любые объекты (только CGFloat или void) – borrrden

+0

@borrrden: «Я не думаю, что методы возвращают какие-либо объекты (только CGFloat или void)». Тогда вы не можете использовать 'performSelector:'. Он возвращает объекты (void, вероятно, хорошо). Последствия ARC возможны только в том случае, если вы используете 'performSelector:' для вызова чего-то типа 'alloc',' keep', 'new',' copy' или 'mutableCopy' или что-то подобное с необычными правилами управления памятью. – newacct

+0

Упс, я использовал NSInvocation для CGFloat, которые были @newacct. Все остальные недействительны. Я полагал, что это было для некоторых менее очевидных случаев. Я не вижу утечек в своей программе. – borrrden