Data transfer in Swift refers to how you pass and share data between:
- View Controllers
- Views and ViewModels
- Screens/Modules
- Background tasks and UI
- Across the app (via singletons, UserDefaults, etc.)
Swift offers multiple techniques, depending on context (UIKit, SwiftUI, architecture). Here’s a full breakdown:
1. Passing Data Between View Controllers (UIKit)
1.1 Forward Passing (Parent ➡️ Child)
Example:
class ProfileViewController: UIViewController { var username: String? // 🔹 Property to receive data
}
let profileVC = ProfileViewController()
profileVC.username = "shomil" // Pass data before push
navigationController?.pushViewController(profileVC, animated: true)
1.2 Backward Passing (Child ➡️ Parent)
Using Delegate Pattern:
protocol SettingsDelegate: AnyObject { func didUpdateTheme(to darkMode: Bool)
}
class SettingsViewController: UIViewController { weak var delegate: SettingsDelegate? func toggleTheme() { delegate?.didUpdateTheme(to: true) }
}
1.3 Using Closures (Callback)
class DetailViewController: UIViewController { var onDataUpdate: ((String) -> Void)? func saveChanges() { onDataUpdate?("Updated Data") }
}
2. Using Segues (Storyboard)
In prepare(for:sender:), set data before navigation:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let destination = segue.destination as? DetailVC { destination.data = "Some text" }
}
3. Using ViewModel (MVVM)
In MVVM, data flows from Model ➡ ViewModel ➡ View
class UserViewModel { let name: String init(user: User) { self.name = user.firstName + " " + user.lastName }
}
struct UserView: View { let viewModel: UserViewModel var body: some View { Text(viewModel.name) }
}
4. Using Singleton (Global Access)
class AppData { static let shared = AppData() var isLoggedIn = false
}
Access from anywhere:
AppData.shared.isLoggedIn = true
5. Using NotificationCenter
Post and listen for broadcast messages (loose coupling):
NotificationCenter.default.post(name: .dataUpdated, object: "New Value")
NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: .dataUpdated, object: nil)
6. UserDefaults / Keychain (Persistent Transfer)
- UserDefaults: For small, non-sensitive data
- Keychain: For secure data like tokens, passwords
UserDefaults.standard.set("Shomil", forKey: "username")
let name = UserDefaults.standard.string(forKey: "username")
7. API/Network Transfer
For remote data transfer (JSON, REST APIs):
URLSession.shared.dataTask(with: url) { data, response, error in // Parse JSON, return model
}
8. Data Transfer in SwiftUI
Use @State, @Binding, @ObservedObject, @EnvironmentObject to pass and share data.
struct ChildView: View { @Binding var isOn: Bool
}
@ObservedObject var viewModel = ProfileViewModel()
Conclusion
Swift gives you many ways to pass data, from simple property setting to advanced patterns like delegates and closures. Choosing the right method depends on direction, complexity, and architecture. To implement clean and efficient data flow, you can hire Swift developers who are experienced with both UIKit and SwiftUI patterns.