3

便利な初期化子を追加して、Swift 3 でFoundation のTimerクラスを拡張しようとしています。しかし、Foundation 提供のイニシャライザへの呼び出しは返されません。

この問題は、Playground として実行できる次の簡単なデモで説明されています。

import Foundation

extension Timer {
    convenience init(target: Any) {
        print("Next statement never returns")
        self.init(timeInterval: 1.0,
                  target: target,
                  selector: #selector(Target.fire),
                  userInfo: nil,
                  repeats: true)
        print("This never executes")
    }
}

class Target {
    @objc func fire(_ timer: Timer) {
    }
}

let target = Target()
let timer = Timer(target: target)

コンソール出力:

次のステートメントは返されません

さらに勉強するには、

• 同様の拡張コードを作成URLProtocolしました (インスタンス初期化子を持つ唯一の他の Foundation クラスの 1 つ)。結果:問題ありません。

• 考えられる原因として Objective-C のものを排除するために、ラップされたイニシャライザをinit(timeInterval:repeats:block:)メソッドに変更し、Swift クロージャを提供しました。結果: 同じ問題。

4

3 に答える 3

4

実際には答えはわかりませんが、デバッガーを使用して実際のアプリでこれを実行すると、無限再帰があることがわかります (したがって、ハングします)。これは、実際にはタイマーの指定された初期化子を呼び出していないためだと思われます。この事実は明らかではありませんが、Timer をサブクラス化してコンパイラを呼び出そうとすると、エラーが発生し、ヘッダーsuper.init(timeInterval...)に奇妙な「継承されていません」というマークが表示されます。super.init(timeInterval...)

self.init(fireAt:...)代わりに次のように呼び出すことで、この問題を回避できました。

extension Timer {
    convenience init(target: Any) {
        print("Next statement never returns") // but it does
        self.init(fireAt: Date(), interval: 1, target: target, 
            selector: #selector(Target.fire), userInfo: nil, repeats: true)
        print("This never executes") // but it does
    }
}

それをあなたがするものにしてください...

于 2016-12-24T22:18:26.407 に答える
0

@mattの回答が機能します。

はい、私のアプリでもその無限再帰を見ました – CFReleases. Swift book は、便利な初期化子が指定された初期化子を呼び出さなければならないことを明確にしています。ただし、何のペナルティかは明言されていません。驚くべきことですが、無限再帰はもっともらしいです。

ただし、Xcode でこれらのメソッドのいずれかをオプション クリックまたはコマンド クリックすると表示される次の 2 つの宣言を見てください。

init(timeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void)

convenience init(fire date: Date, interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void)

そこに何か問題があると思います。私にとって問題を解決する追加の(「fire」)パラメーターを使用して@mattが提案した関数は、便利とマークされています。私が使用した機能は、便利とはマークされていませんが、(Swiftの初心者として)指定されていると思います。ただし、パラメーターが 1 つ少なくなっています。は?

Apple が何らかの形で便利なキーワードを間違った機能で取得したことを示すバグを報告する必要があると思います。これは、Swift がヘッダー ファイルを実際に持っていないため可能である可能性がありますね。では、Foundation 関数をオプション クリックすると、何が表示されるのでしょうか。人的エラーの影響を受けやすいワークフローのステップがある可能性はありますか?

于 2016-12-25T07:46:17.840 に答える