2017-07-31 4 views
0

質問タイトルを作成する際に問題がありました。次のログイン時にGCDベースのログインタイムアウトが発生することがあります

私はタイムアウトを追加するには、ログイン手順があります。

private func startTimeout() { 
    self.timeoutActive = true 
    DispatchQueue.main.asyncAfter(deadline: .now() + 20) { 
     [weak self] in 
     guard let weakSelf = self else { 
      return 
     } 

     if weakSelf.timeoutActive && !weakSelf.loggedIn { 
      weakSelf.onError("Login timed out") 
     } 
    } 
} 

私たちは何らかの理由でログアウトした後(たとえば、再度ログインする必要がある場合ように、ログイン手順を設計し、又は後にしているがログインプロセスは、クレデンシャルがないか間違っていると判断した場合)、ログインを実行するクラスの同じインスタンスになります。

私が見る限り、スケジュールされたブロックが実行されるのを防ぐことはできません。フラグを使用することでそれを防ぐことができます。これは、timeoutActiveフラグで行ったことです。これは魅力のように機能します。

しかし、新しいログインプロセスが開始された後に以前のディスパッチブロックが実行されるように、2番目のログインが正確にタイムアウトすると問題に遭遇します(新しいログインプロシージャが開始されると、timeoutActiveフラグが再度trueに設定されます)。 )。新しいログインは、正しくないタイムアウトを受け取ります。

私はそれを解決するさまざまな方法について考えていましたが、いくつか試しましたが、いずれも動作させることができませんでした。

GCDの代わりにperformSelectorAfterDelayを使用する考えがありました。これは取り消し可能ですが、Swift(3)では利用できません。

ブロックされたブロックIDのリストを持つ一意のブロックIDを持っていると考えられていましたが、残念です。

ブロック内の現在のディスパッチ時間(.now())と元の期限(.now()+ 20)を比較し、それが一致するかどうかを確認するアイデアもありましたが、このデッドラインは不安定であると感じています。

残っている唯一のアイデアは、タイムアウトが含まれているログインプロシージャの周りのオブジェクトのようなタスクを作成して、別のログイン用にそのタスクの新しいインスタンスを作成することです。ちょっとした仕事のようだし、もっと簡単な方法を見つけたら、私は好きだろう。

誰もこの種の状況に遭遇したことがありますか?

+0

Swift3で 'performSelectorAfterDelay'が利用できるようになりましたが、他のperformセレクタメソッドと同じように' perform(...) 'という名前に変更されました。また、キャンセル可能な 'DispatchWorkItem'を作成してから' asyncAfter(...) 'することもできます。 – dan

+0

Xcodeは3つのperform(...)メソッドを前に示していましたが、 "after"パラメータは使用できませんでした。私の悪い。 DispatchWorkItemは私のために新しく、私はそれを試しています。ありがとうございました:) – Joakim

+0

@ダンそれは完璧に働いていただきありがとうございます。あなたがしなかったので私はこれを答えとして掲示しましたが、代わりに答えを掲示すれば私は私を取り除きます。 – Joakim

答えて

0

これは、私が質問にダンさんのコメントから作られたものです。

private var timeoutBlock: DispatchWorkItem? = nil 

private func startTimeout() { 
    self.timeoutBlock = DispatchWorkItem(block: { [weak self] in 
     guard let weakSelf = self else { 
      return 
     } 

     if !weakSelf.loggedIn { 
      weakSelf.onError("Login timed out") 
     } 
    }) 

    DispatchQueue.main.asyncAfter(wallDeadline: .now() + 20, execute: self.timeoutBlock!) 
} 

とのViewControllerを残したり、プロセスを完了したときにself.timeoutBlock?.cancel()を使用。これは期待どおりに動作します!

関連する問題