Swift4 Xcode9:自定义XIB单元格UISwitch状态恢复问题求助
Hey Doug! Let's walk through what you've accomplished so far and figure out how to fix that lingering issue when users re-enter your settings ViewController.
What You've Already Built Great
- Connected to a remote data source that dynamically pulls data into your
ViewController, and correctly populates the.titleand.subtitleproperties of your custom reusable table view cells - The
UISwitchin each cell can already identify the corresponding group (via the cell's title/subtitle) and send "subscribe" or "unsubscribe" signals for push notifications
The Remaining Issue & Fixes (Assuming Switch State Doesn't Persist)
I’m guessing the problem you’re hitting is that when users navigate back to the settings ViewController, the UISwitch states don’t match their previous subscription choices. Here’s how to solve that:
1. Save Subscription State Locally
First, when a user toggles the switch, save their choice to local storage along with sending the subscription signal. UserDefaults is perfect for lightweight state like this; for more complex data, use Core Data instead:
@objc private func handleSwitchToggle(_ sender: UISwitch) { // Get the parent cell to identify the group guard let cell = sender.superview?.superview as? CustomTableViewCell else { return } let groupKey = cell.titleLabel?.text ?? "unknown_group" // Use a unique identifier (like a group ID if titles can repeat) // Save the state UserDefaults.standard.set(sender.isOn, forKey: "subscribed_\(groupKey)") // Send your subscribe/unsubscribe signal if sender.isOn { // Trigger subscribe logic for this group } else { // Trigger unsubscribe logic for this group } }
2. Restore Switch State When Loading Cells
In your tableView(_:cellForRowAt:) method, after setting the cell's title and subtitle, pull the saved state from local storage and apply it to the switch:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "YourCustomCellID", for: indexPath) as! CustomTableViewCell let group = yourRemoteDataSource[indexPath.row] // Populate cell content cell.title = group.title cell.subtitle = group.subtitle // Restore switch state let groupKey = group.title // Replace with group.id if titles aren't unique let isSubscribed = UserDefaults.standard.bool(forKey: "subscribed_\(groupKey)") cell.subscriptionSwitch.isOn = isSubscribed // Attach the toggle handler (make sure you don't add this multiple times!) cell.subscriptionSwitch.addTarget(self, action: #selector(handleSwitchToggle(_:)), for: .valueChanged) return cell }
3. Sync With Remote State (Optional)
If your remote API stores the user's subscription status, sync that local state when you fetch the remote data to avoid mismatches:
private func fetchRemoteGroups() { // Example API call YourAPIService.fetchGroups { [weak self] result in guard let self = self else { return } switch result { case .success(let groups): self.yourRemoteDataSource = groups // Sync remote subscription states to local storage groups.forEach { group in UserDefaults.standard.set(group.isSubscribed, forKey: "subscribed_\(group.title)") } self.tableView.reloadData() case .failure(let error): // Handle error, maybe fall back to local state print("Failed to fetch groups: \(error)") } } }
Quick Pro Tips
- Use a unique group identifier: If group titles can repeat, use a dedicated
idfield from your data model instead of the title for saving state - Avoid overwriting state: If you're fetching remote data, only update local state if the remote data is fresh and reliable
- Clean up old state: If groups get removed from the remote source, consider purging their saved state from
UserDefaultsto avoid clutter
内容的提问来源于stack exchange,提问作者Doug Joseph

