Swift中如何用API自定义时间替代Date()实现UILabel实时更新?
Hey there! The issue you're facing makes total sense—when you use Date() directly, it grabs the current local time every second, so the update happens naturally. But the API gives you a fixed point in time (like "2018-12-10 17:29:50"), which won't tick forward on its own.
You don't need to replace Date() entirely, but you'll need to track the server's starting time and calculate the elapsed time since you first received that server time. Here's how to make it work:
Step 1: Define Required Variables
Add these properties to your view controller to keep track of the server's base time and when you started the timer locally:
var timer: Timer! var serverBaseDate: Date! var timerStartLocalDate: Date!
Step 2: Parse the API Time String to a Date
Convert the API's string response into a Date object. Make sure your DateFormatter matches the format and time zone used by your API:
func parseServerTimeString(_ timeString: String) -> Date? { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" formatter.timeZone = TimeZone(identifier: "UTC") // Adjust this to your API's time zone! return formatter.date(from: timeString) }
Step 3: Initialize Timer and Track Times
In viewDidLoad (or right after you receive the API response), set up the server base time, record the local time when you start the timer, then launch the timer:
override func viewDidLoad() { super.viewDidLoad() // Simulate API response (replace this with your actual API call result) let apiTimeString = "2018-12-10 17:29:50" guard let serverTime = parseServerTimeString(apiTimeString) else { print("Failed to parse server time") return } serverBaseDate = serverTime timerStartLocalDate = Date() // Record when we start tracking // Start the timer timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(tick), userInfo: nil, repeats: true) }
Step 4: Update UILabel with Calculated Server Time
In your tick method, calculate how much time has passed since you started the timer, add that to the server's base time, then format and display it:
@objc func tick() { guard let serverBase = serverBaseDate, let startLocal = timerStartLocalDate else { return } // Calculate elapsed time since timer started let elapsedTime = Date().timeIntervalSince(startLocal) // Add elapsed time to server's base time to get current "server time" let currentServerTime = serverBase.addingTimeInterval(elapsedTime) // Format and update the label let formattedTime = DateFormatter.localizedString(from: currentServerTime, dateStyle: .none, timeStyle: .medium) serverTime.text = formattedTime }
A Quick Note on Calendar.current
You don't strictly need Calendar.current here unless you need to do granular date calculations (like adding days/months). This time-interval approach is simpler for just ticking the clock forward accurately based on the server's starting time.
Don't forget to clean up the timer to avoid memory leaks:
deinit { timer?.invalidate() }
内容的提问来源于stack exchange,提问作者amaulana

