2009-05-28 3 views
157

Есть ли простой способ задержать вызов метода в течение 1 секунды?Как отложить вызов метода на 1 секунду?

У меня есть UIImageView, который реагирует на событие касания. Когда обнаружено касание, некоторые анимации происходят в приложении. Через одну секунду я хочу вызвать другой метод. В этом случае я не могу использовать селектор animationDidStop.

+0

Там являются certai несколько способов сделать это, одним из них может быть просто использовать sleep() для приостановки программы/потока на несколько миллисекунд **, но ** я думаю, вы можете сказать нам, что именно вы пытаетесь выполнить это? Я имею в виду, какова ваша фактическая проблема? Идея отсрочить вызов метода кажется «решением», которое не кажется слишком хорошим, чтобы быть честным. Итак, просто расскажите нам больше о сценарии, который вы имеете в виду. – none

ответ

243
performSelector:withObject:afterDelay: 

Document Reference

+6

Это правильный ответ. См. Http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelector:withObject:afterDelay: – harms

+1

Отличный ответ! Работает отлично. – Thanks

+2

Это то, что вы можете получить, предоставив тщательно сформулированный вопрос в первую очередь :-) – none

-37

ПРИМЕЧАНИЕ: это приостановит всю вашу нить, а не только один метод.
Сделайте вызов для ожидания/ожидания/остановки за 1000 мс перед вызовом вашего метода?

Sleep(1000); // does nothing the next 1000 mSek 

Methodcall(params); // now do the real thing 

Edit: Вышеуказанный ответ относится к общему вопросу: «Как я могу задержать вызов метода в течение 1 секунды?», Который был вопрос, заданный во время ответа (Infact ответ был дан в течение 7 минут оригинального вопроса :-)). Нет информации было дано о языке в то время, так любезно прекратить скулить о правильном пути использования сна я Xcode О.Г. отсутствие классов ...

+0

, который остановил бы все в приложении, не так ли? – Thanks

+0

Только в текущей теме продолжаются другие потоки. –

+3

Geez. Я понимаю, почему это было пропущено несколько раз, но кто это видел? -27, и решил, что нужен другой? Делает -3 или что-то не получается. Почему бы просто не отредактировать ответ, чтобы сказать «это остановит всю вашу нить» или что-то вместо того, чтобы опрокинуть его людей? –

123

Лучший способ сделать это :

[self performSelector:@selector(YourFunctionName) 
      withObject:(can be Self or Object from other Classes) 
      afterDelay:(Time Of Delay)]; 

вы также можете передавать ноль, как с параметромObject.

пример:

[self performSelector:@selector(subscribe) withObject:self afterDelay:3.0 ]; 
+3

Зачем вам проходить самообслуживание? – Eric

+2

И зачем вам передавать переменную методам, принимающим нулевые аргументы? – hellozimi

17

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

[self performSelector:@selector(InsertView) withObject:nil afterDelay:0.1]; 
167

Вы также можете использовать блок

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
    [object method]; 
}); 

Большинство времени вы будете хотеть использовать dispatch_get_main_queue, хотя, если нет пользовательского интерфейса в методе вы можете использовать global queue.

Edit:

Swift 3 версия:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 
    object.method() 
} 

Одинаково, DispatchQueue.global().asyncAfter(... также может быть хорошим вариантом.

+0

Найдено это решение будет проще, чем performSelector при смешивании прямой C и ObjC –

+1

К сожалению dispatch_get_current_queue является устаревшим с iOS6 – chrisben

+3

Обновлено использовать dispatch_get_main_queue вместо dispatch_get_current_queue – mcfedr

8

Вы также можете:

[UIView animateWithDuration:1.0 
       animations:^{ self.view.alpha = 1.1; /* Some fake chages */ } 
       completion:^(BOOL finished) 
{ 
    NSLog(@"A second lapsed."); 
}]; 

В этом случае вы должны фальсифицировать некоторые изменения в той или иной точки зрения, чтобы получить анимационную работу. Это действительно хак, но я люблю блок-материал. Или заверните @mcfedr ответ ниже.


waitFor(1.0,^
{ 
    NSLog(@"A second lapsed"); 
}); 

typedef void (^WaitCompletionBlock)(); 
void waitFor(NSTimeInterval duration, WaitCompletionBlock completion) 
{ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC), 
        dispatch_get_main_queue(),^
    { completion(); }); 
} 
+0

Не уверен, но я думаю, что первый вариант, который вы предлагаете, может иметь побочные эффекты, о которых должны знать пользователи, например, блокирование взаимодействия с пользователем на части пользовательского интерфейса. Мой инстинкт заключается в том, что это также вызовет ненужный CPU или другой ресурс, но я не проверял. –

7

Вы можете сделать это

[self performSelector:@selector(MethodToExecute) withObject:nil afterDelay:1.0 ]; 
20

Есть уже много ответов, и они все правильно. Если вы хотите использовать dispatch_after, вы должны найти фрагмент, который включен в Code Snippet Library в правом нижнем углу (где вы можете выбрать UI элементов).

enter image description here

Так что вам просто нужно вызвать этот фрагмент, написав отправка в коде:

enter image description here

0

Существует решение Swift 3 из проверенного решения:

self.perform(#selector(self.targetMethod), with: self, afterDelay: 1.0) 

И есть способ

@objc fileprivate func targetMethod(){ 

} 
1

Swift 2.x

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))) 
dispatch_after(delayTime, dispatch_get_main_queue()) { 
print("do some work") 
} 

Swift 3.x - & - Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { 
    print("do some work") 
} 
0

Использование в Swift 3

perform(<Selector>, with: <object>, afterDelay: <Time in Seconds>)