带Completion的Timer Selector函数调用出现EXC_BAD_ACCESS错误求助
Hey there, let's break down why you're hitting that EXC_BAD_ACCESS error and how to fix it.
The Root Cause
When you use #selector with a Timer, the system expects the target method to match one of two specific signatures:
- A method with no parameters:
@objc func methodName() - A method that accepts the triggering Timer as its only parameter:
@objc func methodName(_ timer: Timer)
Your fetchDatabase(completion:) method has a closure parameter, which translates to an Objective-C block under the hood. When the Timer fires, it tries to call your method without passing that block parameter—this mismatch between what the method expects and what the Timer provides causes the memory access crash.
The Solution: Wrap the Call
The cleanest way to handle this is to create a dedicated "bridge" method that the Timer can call, and inside that method, invoke your fetchDatabase with the completion handler you want. Here's how:
- Add the wrapper method to your class:
@objc private func handleTimerFetch() { fetchDatabase { result in // Put your completion logic right here if result { print("Database fetch succeeded!") } else { print("Database fetch failed.") } } }
- Update your Timer initialization to use this new selector:
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(handleTimerFetch), userInfo: nil, repeats: true)
Why This Works
- The
handleTimerFetchmethod matches the signature the Timer expects (no parameters), so the system can call it safely when the Timer fires. - Inside this wrapper, you get full control over calling
fetchDatabasewith your desired completion logic, avoiding the signature mismatch that caused the crash.
A Quick Note on Selector Signatures
If you ever need to access the Timer itself in your wrapper (e.g., to invalidate it early), you can adjust the wrapper to accept the Timer parameter:
@objc private func handleTimerFetch(_ timer: Timer) { fetchDatabase { result in // Your logic here if !result { timer.invalidate() // Stop the timer if fetch fails } } }
Then update the Timer call to use this selector:
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(handleTimerFetch(_:)), userInfo: nil, repeats: true)
内容的提问来源于stack exchange,提问作者Alex Wulff

