'pass data from web server and show it on viewcontroller
I have data from a server which I need to show on another View Controller. Note I had perform a POST request. Note I have 2 ViewControllers
these are the fields:
firstName
lastName
emailAddress
mobileNumber
This is the code that started the web service POST (data downloaded)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let profileVC = segue.destination as? ProfileViewController else {return}
profileVC.nameLabel.text = self.firstName
profileVC.idNumberLabel.text = self.idNumber
profileVC.emailAddressLabel.text = self.emailAddress
profileVC.mobileNumberLabel.text = self.mobileNumber
This is where the downloaded data is supposed to show
private func updateUI(firstName: String, lastName: String, emailAddress: String, mobileNumber: String) {
self.nameLabel.text = firstName + "" + lastName
self.idNumberLabel.text = idNumber
self.emailAddressLabel.text = emailAddress
}
this is the post request code
// Prepare URL
let url = URL(string: stringURL)
guard let requestUrl = url else { fatalError() }
// Prepare URL Request Object
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
// Set HTTP Request header
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("1088", forHTTPHeaderField: "Content-Length")
// HTTP Parameters which will be sent in HTTP Request body
let postString = "userID=\(useridTextField.text)&password=\(passwordTextField.text)";
// Set HTTP Request Body
request.httpBody = postString.data(using: String.Encoding.utf8)
// Perform HTTP Request
let session = URLSession.shared
let task = session.dataTask(with: request) { data, response, error in
guard let data = data else {
return
}
do {
var response = try JSONDecoder().decode(User.self, from: data)
response.idNumber = self.idNumber
response.firstName = self.firstName
response.middleName = self.middleName
response.lastName = self.lastName
response.emailAddress = self.emailAddress
response.mobileNumber = self.mobileNumber
response.landline = self.landline
return
} catch {
let str = String(decoding: data, as: UTF8.self)
print(str)
}
}
task.resume()
Solution 1:[1]
Here is an example using Publish/Observer pattern with Notifications
I start with this simple extension that helps me organize notification names
extension Notification.Name {
static let DidLoginSuccessfully
= Notification.Name("DidLoginSuccessfully")
}
Let's say you have a Network class with a launch request function that launches your network request.
Once you have successfully got a response and decoded your response to a URL object, you can publish / post a notification to any observers
fileprivate func launchRequest() {
// Prepare URL
let url = URL(string: stringURL)
guard let requestUrl = url else { fatalError() }
// Prepare URL Request Object
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
// Set HTTP Request header
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("1088", forHTTPHeaderField: "Content-Length")
// HTTP Parameters which will be sent in HTTP Request body
let postString = "userID=\(useridTextField.text)&password=\(passwordTextField.text)";
// Set HTTP Request Body
request.httpBody = postString.data(using: String.Encoding.utf8)
// Perform HTTP Request
let session = URLSession.shared
let task = session.dataTask(with: request) { data, response, error in
guard let data = data else {
return
}
do {
// Change response variable name to user
var user = try JSONDecoder().decode(User.self, from: data)
user.idNumber = self.idNumber
user.firstName = self.firstName
user.middleName = self.middleName
user.lastName = self.lastName
user.emailAddress = self.emailAddress
user.mobileNumber = self.mobileNumber
user.landline = self.landline
// Publish the notification
NotificationCenter.default.post(name: .DidLoginSuccessfully,
object: user)
} catch {
let str = String(decoding: data, as: UTF8.self)
print(str)
}
}
task.resume()
}
Then in the module where you need some data to be updated, you need to observe / listen this notification
For example, let's say this was a view controller, you need to observe this notification and when you get notified of this event, you need to manage this.
class SomeCustomVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
subscribeToNotifications()
}
deinit {
unsubscribeFromNotifications()
}
private func subscribeToNotifications() {
// Sets the view controller to list to this notification
NotificationCenter.default.addObserver(self,
selector: #selector(didLoginSuccessfully(_:)),
name: .DidLoginSuccessfully,
object: nil)
}
// Your button login event handler
private func didTapLoginButton() {
// Make the segue or API request as you do
}
private func unsubscribeFromNotifications() {
NotificationCenter.default.removeObserver(self,
name: .DidLoginSuccessfully,
object: nil)
}
// Your update UI function
private func updateUI(firstName: String,
lastName: String,
emailAddress: String,
mobileNumber: String) {
self.nameLabel.text = firstName + "" + lastName
self.idNumberLabel.text = idNumber
self.emailAddressLabel.text = emailAddress
}
}
// Notification Observer
extension SomeCustomVC {
@objc func didLoginSuccessfully(_ notification: Notification) {
if let user = notification.object as? User {
updateUI(firstName: user.firstName,
lastName: user.lastName,
emailAddress: user.emailAddress,
mobileNumber: user.mobileNumber)
}
}
}
Give this a go and see if it helps you.
If you are looking for something more sophisticated like binding, you can have a look at this Combine tutorial.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Shawn Frank |
