NSObject
Метод performSelector:withObject:afterDelay:
позволяет мне вызвать метод объекта с объектом спора по истечении определенного времени. Его нельзя использовать для методов с аргументом, не являющимся объектом (например, целые числа, числа с плавающей запятой, структуры, указатели, не являющиеся объектами, и т. Д.).
Каков самый простой способ добиться того же с помощью метода с аргументом, не являющимся объектом? Я знаю, что для обычных performSelector:withObject:
пользователей решение - использовать NSInvocation
(что, кстати, действительно сложно). Но я не знаю, как справиться с «задержкой».
Спасибо,
objective-c
cocoa
user102008
источник
источник
Ответы:
Вот что я называл тем, что не мог изменить с помощью NSInvocation:
источник
[theMovie setOrientation: UIInterfaceOrientationPortrait animated:NO]
? Или вы имеете в виду, чтоinvoke
сообщение находится в методе, который вы выполняете после задержки?Просто заверните float, boolean, int или аналогичные в NSNumber.
Для структур я не знаю удобного решения, но вы могли бы создать отдельный класс ObjC, который владеет такой структурой.
источник
nil
дляBOOL
параметра получитьNO
(FALSE
)НЕ ИСПОЛЬЗУЙТЕ ЭТОТ ОТВЕТ. Я ОСТАВЛЯЛ ЕГО ТОЛЬКО ДЛЯ ИСТОРИЧЕСКИХ ЦЕЛЕЙ. СМОТРЕТЬ КОММЕНТАРИИ НИЖЕ.
Если это параметр типа BOOL, есть простой трюк.
Передайте nil вместо NO и self для YES. nil приводится к значению BOOL NO. self приводится к значению BOOL YES.
Этот подход не работает, если это какой-либо параметр, кроме BOOL.
Предполагая, что self - это UIView.
источник
if ()
проверять его, но вполне возможно, что какой-то код будет зависеть от его значения 0 или 1, и, таким образом, выиграл не рассматривать какое-либо большое значение адреса как то же самое, что и 1 (ДА).self
с адресом вроде0x0123400
. При таком подходе вы НЕ получите ДА в 0,4% случаев. Хуже того, с этой вероятностью это решение может пройти все тесты и раскрыться позже.Возможно, NSValue , просто убедитесь, что ваши указатели все еще действительны после задержки (т. Е. Нет объектов, размещенных в стеке).
источник
NSValue
(если возможно) ожидаемыйtype
?Я знаю, что это старый вопрос, но если вы создаете iOS SDK 4+, вы можете использовать блоки, чтобы сделать это с очень небольшими усилиями и сделать его более читаемым:
источник
PerformSelector: WithObject всегда принимает объект, поэтому для передачи аргументов типа int / double / float и т. Д. Вы можете использовать что-то вроде этого.
Таким же образом вы можете использовать [NSNumber numberWithInt:] и т. Д. И в методе получения вы можете преобразовать число в свой формат как [number int] или [number double].
источник
Блоки - это то, что нужно. У вас могут быть сложные параметры, безопасность типов, и это намного проще и безопаснее, чем большинство старых ответов здесь. Например, вы можете просто написать:
Блоки позволяют захватывать произвольные списки параметров, ссылочные объекты и переменные.
Поддержка реализации (базовая):
Пример:
Также см. Ответ Майкла (+1) для другого примера.
источник
Я всегда рекомендую использовать NSMutableArray в качестве объекта для передачи. Это потому, что затем вы можете передать несколько объектов, например, нажатую кнопку и другие значения. NSNumber, NSInteger и NSString - это просто контейнеры некоторой ценности. Убедитесь, что при получении объекта из массива, на который вы ссылаетесь, используется правильный тип контейнера. Вам нужно передать NS-контейнеры. Там вы можете проверить значение. Помните, что контейнеры используют isEqual при сравнении значений.
источник
Я тоже хотел это сделать, но с помощью метода, который получает параметр типа BOOL. Обертывание значения типа bool с помощью NSNumber, НЕ удалось передать значение. Понятия не имею почему.
В итоге я сделал простой хак. Я помещаю требуемый параметр в другую фиктивную функцию и вызываю эту функцию с помощью performSelector, где withObject = nil;
источник
-performSelector[...]
метод ожидает объект (вместо примитивного типа данных) и не знает, что вызываемый селектор принимает логическое значение, возможно, адрес (значение указателя)NSNumber
экземпляра слепо 'приведен' кBOOL
(= ненулевое, т.е.TRUE
). Возможно, среда выполнения могла бы быть умнее этого и распознавать нулевое логическое значение, заключенное вNSNumber
!Я считаю, что самый быстрый (но несколько грязный) способ сделать это - напрямую вызвать objc_msgSend. Однако вызывать его напрямую опасно, потому что вам нужно прочитать документацию и убедиться, что вы используете правильный вариант для типа возвращаемого значения, и потому что objc_msgSend определен как vararg для удобства компилятора, но фактически реализован как клей для быстрой сборки . Вот код, используемый для вызова метода делегата - [delegate integerDidChange:], который принимает единственный целочисленный аргумент.
Это сначала сохраняет селектор, так как мы будем ссылаться на него несколько раз, и было бы легко допустить опечатку. Затем он проверяет, действительно ли делегат отвечает на селектор - это может быть дополнительный протокол. Затем он создает тип указателя функции, который указывает фактическую сигнатуру селектора. Имейте в виду, что все сообщения Objective-C имеют два скрытых первых аргумента: отправляемый объект и отправляемый селектор. Затем мы создаем указатель функции соответствующего типа и устанавливаем его так, чтобы он указывал на базовую функцию objc_msgSend. Имейте в виду, что если возвращаемое значение - это число с плавающей запятой или структура, вам нужно использовать другой вариант objc_msgSend. Наконец, отправьте сообщение, используя тот же механизм, который Objective-C использует под листами.
источник
Вы можете просто использовать NSTimer для вызова селектора:
источник
yourMethod:
в вашем примере является сам таймер, а вы ничего не передалиuserInfo
. Даже если бы вы использовалиuserInfo
, вам все равно придется упаковать ценность, как предлагали Хармс и Ремус Русану.Вызов performSelector с NSNumber или другим NSValue работать не будет. Вместо использования значения NSValue / NSNumber он будет эффективно приводить указатель к типу int, float или чему-то еще и использовать его.
Но решение простое и очевидное. Создайте NSInvocation и позвоните
[invocation performSelector:@selector(invoke) withObject:nil afterDelay:delay]
источник
Возможно ... ладно, скорее всего, я что-то упускаю, но почему бы просто не создать объектный тип, скажем NSNumber, в качестве контейнера для вашей переменной не-объектного типа, такой как CGFloat?
источник