Swift - 防止计时器重复

时间:2016-11-09 15:54:49

标签: ios swift xcode timer swift3

我有一个在viewDidLoad

中运行的计时器
_ = Timer.scheduledTimer(timeInterval: 10,
                                   target: self,
                                   selector: #selector(timerFired),
                                   userInfo: nil,
                                   repeats: true)

计时器工作正常,问题是因为多次调用viewDidLoad,计时器重复。

有没有办法确保我的计时器只运行一次?

2 个答案:

答案 0 :(得分:3)

您需要保留对计时器的引用,以便在viewController消失时使其无效。否则它将继续运行,并且每次创建另一个viewController时都会生成新的计时器。

LDAP server: 10.10.1.2
LDAP server name: cz1.company.local
Realm: COMPANY.LOCAL
Bind Path: dc=COMPANY,dc=LOCAL
LDAP port: 389
Server time: Wed, 09 Nov 2016 16:46:09 CET
KDC server: 10.10.1.2
Server time offset: 0
Last machine account password change: Wed, 09 Nov 2016 16:34:20 CET

根据您的导航逻辑[2016/11/09 16:51:23.751082, 3] ../source3/auth/auth.c:178(auth_check_ntlm_password) check_ntlm_password: Checking password for unmapped user [COMPANY]\[administrator]@[CZ2] with the new password interface [2016/11/09 16:51:23.751106, 3] ../source3/auth/auth.c:181(auth_check_ntlm_password) check_ntlm_password: mapped user is: [COMPANY]\[administrator]@[CZ2] [2016/11/09 16:51:23.781423, 3] ../source3/auth/auth.c:249(auth_check_ntlm_password) check_ntlm_password: winbind authentication for user [administrator] succeeded [2016/11/09 16:51:23.781482, 2] ../source3/auth/auth.c:305(auth_check_ntlm_password) check_ntlm_password: authentication for user [administrator] -> [administrator] -> [COMPANY/administrator] succeeded [2016/11/09 16:51:23.781650, 3] ../auth/ntlmssp/ntlmssp_sign.c:509(ntlmssp_sign_reset) NTLMSSP Sign/Seal - Initialising with flags: [2016/11/09 16:51:23.781671, 3] ../auth/ntlmssp/ntlmssp_util.c:69(debug_ntlmssp_flags) Got NTLMSSP neg_flags=0x62088215 [2016/11/09 16:51:23.781716, 3] ../auth/ntlmssp/ntlmssp_sign.c:509(ntlmssp_sign_reset) NTLMSSP Sign/Seal - Initialising with flags: [2016/11/09 16:51:23.781731, 3] ../auth/ntlmssp/ntlmssp_util.c:69(debug_ntlmssp_flags) Got NTLMSSP neg_flags=0x62088215 [2016/11/09 16:51:23.783333, 1] ../source3/auth/token_util.c:430(add_local_groups) SID S-1-5-21-2983937313-3188343367-1241514986-500 -> getpwuid(10500) failed [2016/11/09 16:51:23.783370, 3] ../source3/auth/token_util.c:316(create_local_nt_token_from_info3) Failed to finalize nt token [2016/11/09 16:51:23.783395, 1] ../source3/smbd/sesssetup.c:290(reply_sesssetup_and_X_spnego) Failed to generate session_info (user and group token) for session setup: NT_STATUS_UNSUCCESSFUL [2016/11/09 16:51:23.783634, 3] ../source3/smbd/error.c:82(error_packet_set) NT error packet at ../source3/smbd/sesssetup.c(293) cmd=115 (SMBsesssetupX) NT_STATUS_UNSUCCESSFUL [2016/11/09 16:51:23.784947, 3] ../source3/smbd/server_exit.c:246(exit_server_common) Server exit (failed to receive smb request) [2016/11/09 16:51:23.817897, 3] ../source3/lib/util_procid.c:54(pid_to_procid) pid_to_procid: messaging_dgm_get_unique failed: No such file or directory 可能会在取消分配视图之前多次调用,您必须自行决定处理此问题的最佳方法。

答案 1 :(得分:2)

viewDidLoad方法仅在视图控制器的生命周期内调用一次。

如果您运行多个计时器,那么您可能有多个视图控制器实例。否则,当您将视图控制器从导航堆栈中弹出并且计时器尝试再次调用它时,您可能会崩溃。

您需要通过释放它们来平衡您在viewDidLoad中创建的内容。

编辑:

通常通过将清理代码放在deinit方法中来平衡您在viewDidLoad中创建的内容。但是,它看起来像一个正在运行的计时器保持强烈引用它的目标。因此,如果你的视图控制器是一个运行计时器的目标,那么它的deinit方法就不会被调用。

我建议您在viewWillAppear中创建计时器并在viewWillDisappear中使其无效:

weak var timer: Timer?



override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)
  timer = Timer.scheduledTimer(timeInterval: 1.0,
    target: self,
    selector: #selector(timerFired(timer:)), 
    userInfo: nil, repeats: true)
}

override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
  timer?.invalidate()
}

编辑#2:

或者,你可以使用带有而不是目标/选择器的new-to-iOS 10版本的scheduledTimer()。 最终 Apple创建了此功能。关于d * amned time!

weak var timer: Timer?


override func viewDidLoad() {

  super.viewDidLoad()
  timer = Timer.scheduledTimer(withTimeInterval: 1.0,
    repeats: true) {
    [weak self] timer in
    //Your timer code here
}


deinit {
  timer?.invalidate()
}