2017-08-05 30 views
1

在swift中,如何在用戶停止鍵入文本框後1秒鐘運行某些代碼?有textFieldDidChange,但是會在輸入新字符後立即運行代碼。SWIFT - 在用戶停止鍵入文本框後1秒鐘運行代碼

+0

我的回答對你有幫助嗎? –

+0

@ReinierMelian它的工作原理,但我最終做了一些不同的事情,因爲我不想創建一個新的TextView。 – BlueBoy

+0

好@BlueBoy好運!謝謝你讓我知道 –

回答

0

textFieldDidEndEditing(_ :),回覆之前結束,加入這行代碼:

DispatchQueue.global().asyncAfter(deadline: .now() + 1) { 
    doSomething() 
} 

DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 
    doSomething() 
} 
如果你想要做一些事情的UserInterface

(UI )(顯示新視圖,移動框架,開始動畫)

+0

但如果用戶鍵入「嗨」 - 不會有兩個'doSomething()'運行,只延遲一秒? – BlueBoy

+0

對不起。我錯了。委託方法是textFieldDidEndEditing(_ :) – ndPPPhz

+0

但只在文本字段退出第一個響應者之後才運行否? – BlueBoy

3

試着用這個自定義UITextField,你需要設置一個計時器1秒用戶每次把一個角色在你的UITextField,並再次失效重新安排前計時器,我加入了行動,關閉允許任何的動作,充分的自由在你執行

增加檢查屬性對於延遲定製

import UIKit 

@IBDesignable 
class AfterOneSecondTextField: UITextField { 

    @IBInspectable var delayValue : Double = 1.0 
    var timer:Timer? 

    var actionClosure : (()->Void)? 

    override func awakeFromNib() { 
     super.awakeFromNib() 
     self.addTarget(self, action: #selector(changedTextFieldValue), for: .editingChanged) 
    } 

    func changedTextFieldValue(){ 
     timer?.invalidate() 
     //setup timer 
     timer = Timer.scheduledTimer(timeInterval: delayValue, target: self, selector: #selector(self.executeAction), userInfo: nil, repeats: false) 
    } 

    func executeAction(){ 
     actionClosure?() 
    } 

    /* 
    // Only override draw() if you perform custom drawing. 
    // An empty implementation adversely affects performance during animation. 
    override func draw(_ rect: CGRect) { 
     // Drawing code 
    } 
    */ 

} 

使用它

你只需要設置類和閉合傳遞給我的情況你的期望動作是debugPrint但你可以做任何喲u需要

class ViewController: UIViewController { 
    @IBOutlet weak var tfText: AfterOneSecondTextField! 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     tfText.actionClosure = { 
      debugPrint("Test") 
     } 
    } 

這個工作!測試

希望這有助於

0

我所做的是用一個取消關閉一些延遲後運行代碼;就像用戶輸入閉包的方式一直被取消一樣,但是當它們停頓了足夠長時間或者完成搜索或提取的代碼實際上是在短暫的延遲之後運行的。

我用取消關閉代碼從這裏:

Cancel a timed event in Swift?

然後就是進入textFieldDidChange代碼如下:

fileprivate var delayedSearchClosure : dispatch_cancelable_closure? 
open func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 

    if let searchClosure = delayedSearchClosure { 
     searchClosure(true) 
     delayedSearchClosure = .none 
    } 

    delayedSearchClosure = delayClosure(0.8) { [weak self] in 
     self?.doSearch(searchText) 
     self?.delayedSearchClosure = .none 
    } 
} 

爲了解釋這裏發生了什麼 - 在回調作爲用戶類型的文本字段,我首先終止創建在特定時間運行的現有閉包。然後在下一個代碼塊中,它會創建一個新的delayedSearchClosure,它將從現在開始執行0.8秒,並調用「doSearch()」,然後拋棄該閉包。

因此,隨着用戶的類型,關閉被扔掉,不再重要。最終用戶將暫停或停止輸入,此時您要運行的代碼實際上會執行(在這種情況下,將根據文本執行搜索)。這爲您提供了一種感覺反應靈敏的搜索表單,但不會浪費時間爲用戶輸入的每個字符添加搜索(這會增加開銷並開始影響用戶界面性能)。

+0

你的代碼令人困惑... – BlueBoy

+0

@BlueBoy:增加了更多關於發生了什麼的解釋。我喜歡這種方法比基於定時器的方法多一點,因爲我不想使用定時器和自定義類來處理響應。 –