Swift - Pass json data to other views
Here is a simplified version of your code
class AuthViewModel: ObservableObject {
// I don't have your Model info
//You can have an empty object of your model or you can make it an optional, etc
@Published var user: YourModel? = nil
@Published var alert: CustomAlert? = nil
let networkService: NetworkService = NetworkService.shared
var authentication: AuthenticationCheck? = nil
func signIn(username: String, password: String) {
networkService.signIn(username: username, password: password){ (result) in
switch result {
case .success(let user):
print("This user last name is: \(user)")
//Assign you value to the Published variable here
self.user = user
self.authentication?.updateValidation(success: true)
self.alert = CustomAlert(title: "Success", message: "You logged in")
case .failure(let error):
print("The error is: \(error)")
//Reset the variable
self.user = nil
self.authentication?.updateValidation(success: false)
//You can pass a better message to the user like this
self.alert = CustomAlert(title: "Invalid Credentials", message: "\(error)")
}
}
}
func logout() {
self.user = nil
authentication?.updateValidation(success: false)
self.alert = CustomAlert(title: "See you later", message: "You logged out")
}
}
class AuthenticationCheck: ObservableObject {
@Published var isValidated = false
func updateValidation(success: Bool) {
withAnimation {
isValidated = success
}
}
}
struct SampleNetworkView: View {
@StateObject var vm: AuthViewModel = AuthViewModel()
@StateObject var authentication: AuthenticationCheck = AuthenticationCheck()
@State var username: String = ""
@State var password: String = ""
var body: some View {
NavigationView{
switch authentication.isValidated{
case true:
VStack{
Text("Signed In - you are now in the content view")
.toolbar(content: {
Button("log out", action: {
vm.logout()
})
})
}
case false:
VStack{
TextField("username", text: $username).textFieldStyle(RoundedBorderTextFieldStyle())
SecureField("password", text: $password).textFieldStyle(RoundedBorderTextFieldStyle())
Button("sign in", action: {
vm.signIn(username: username, password: password)
}).disabled(username.isEmpty || password.isEmpty)
}
}
}
//Inject the StateObjects to the navigation view so you can access the variables
.environmentObject(authentication)
.environmentObject(vm)
//Create a shared Alert for the ViewModel
.alert(item: $vm.alert, content: { customAlert in
Alert(title: Text(customAlert.title), message: Text(customAlert.message), dismissButton: .default(Text("ok")))
})
//Pass the authentication to the ViewModel so you can pass info
.onAppear(perform: {
vm.authentication = authentication
})
}
}
struct SampleNetworkView_Previews: PreviewProvider {
static var previews: some View {
SampleNetworkView()
}
}
//This assists in creating a shared alert
struct CustomAlert : Identifiable {
let id: UUID = UUID()
var title: String
var message: String
}
How to pass json data in swift app between two viewcontrollers
I would do something like this:
let newController = self.storyboard?.instantiateViewControllerWithIdentifier("newControllerIdentifier") as! NewControllerClassName
newController.data = array
self.navigationController?.pushViewController(newController, animated: true)
It also appears you are using a array of string type that are comma separated.
I would rather create a variable like below
var jsonArray:[[String:String]]?
How to pass JSON data to another view controller from login function using post method?
For loop
here is unnecessary because you are not getting array of Login data what you need is to directly use self.myResponse
to make object of Login
. Also you are performing segue twice with different identifier perform segue to specific identifier with your corresponding destination controller.
Alamofire.request("http://192.168.100.5:84/Token", method: .post, parameters: parameters, encoding: URLEncoding.httpBody, headers: headers).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case.success(let data):
print("success",data)
let statusCode = (response.response?.statusCode)!
if statusCode == 200{
self.view.makeToast(message: "Welcome !!")
}else{
self.view.makeToast(message: "Username or password invalid")
}
self.myResponse = JSON(data)
let login = Login(loginJson: self.myResponse)
DispatchQueue.main.async(execute: { () -> Void in
self.performSegue(withIdentifier: "pass_data", sender: login)
})
case.failure(let error):
print("Not Success",error)
}
}
Now make your prepareForSegue
like this
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "pass_data" {
if let eventsVC = segue.destination as? MenuDrawerViewController,
let loginData = sender as? Login {
eventsVC.login_details = loginData
}
}
}
How do I pass Json Data from one class to another?
Update your fetch data with completion
func fetchWeather(cityName: String,completionHandler: @escaping (WeatherModel?) -> Void){
let weatherURL = "https://api.openweathermap.org/data/2.5/weather?q=\(cityName)&appid=55dbb1b10e9f55181ad910227f1460ae&units=metric"
let objectURL = URL(string: weatherURL)
let task = URLSession.shared.dataTask(with: objectURL!, completionHandler: {(data,reponse,error)in
if error != nil{
print(error!)
} else{
do{
let json = try JSONDecoder().decode(CityWeatherInfo.self, from: data!)
print(json)
let saveData: WeatherModel = WeatherModel(name: json.name,
temp: json.main.temp, feelsLike: json.main.feelsLike,
tempMin: json.main.tempMin, tempMax: json.main.tempMax,
main: json.weathers[0].main, description: json.weathers[0].main)
print(saveData)
completionHandler(saveData)
} catch{
completionHandler(nil)
print("error")
}
}
})
task.resume()
}
How to use
class WeatherDetailViewController: UIViewController {
var weatherPresenter: WeatherDetailPresenter?
public var cityName: String?
let request = RequestManager()
override func viewDidLoad() {
super.viewDidLoad()
request.fetchWeather(cityName: "", completionHandler: { [weak self] weatherModel in
// here you get object and you can set labels
self?.tempMinLabel.text = weatherModel.tempMin
self?. tempMaxLabel.text = weatherModel.tempMax
//....
})
}
}
Passing JSON data from HTTP request to another view controller in Swift 3
You should set up a manual segue in Storyboard
, that you only call inside the completion handler of your network request. If the segue is connected to a single tableview cell, it will be called by the system before your async function would finish execution. Once you changed your segue to be manual and not connected to a static table view cell, you can call it using the function performSegue
.
func retrieveTime(jobDateValue: String) -> Void {
if let crew = user!["crew"] as? [String:Any], let crewID = crew["crew_id"] as? String{
let param = ["action": "retrieve time", "job": ["crew_id": crewID, "jobDate": jobDateValue]] as [String : Any]
let headers = [ "content-type": "application/json", "cache-control": "no-cache" ]
if let postData = (try? JSONSerialization.data(withJSONObject: param, options: [])) {
var request = URLRequest(url: URL(string: "http://52.221.231.3/gv/app_api.php")!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { (data, response, error) -> Void in
guard error == nil, let data = data else {return}
DispatchQueue.main.async{
if let json = (try? JSONSerialization.jsonObject(with: data)) as? [String:Any]{
let result = json["result"] as? String
if (result == "success") {
let passValue = json
self.performSegue(withIdentifier: "YourSegue", sender: json)
} else{
}
}
}
}
task.resume()
}
}
}
Also use native Swift objects when available instead of their Foundation counterparts (such as NSDictionary
, NSMutableURLRequest
).
You should also use the sender
option of performSegue
to send the json
data to your other view controller instead of storing it in another variable unless you use the json
object in your first view controller as well.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SecondVCSegue"{
if let destination = segue.destination as? SecondVC, let json = sender as? [String:Any] {
destination.passedData = json
}
}
}
How to send Json Data to Table View Array? Swift
First you have an empty function showTable
inside your viewDidLoad
- This does nothing. Presumably it is something hanging around from your various attempts. Delete that.
As you have probably worked out, your network fetch operation is going to occur asynchronously and you need to reload the table view once the data has been fetched.
You have some code in viewDidLoad
that kind of tries to do this, but it isn't related to the fetch operation. It is just dispatched asynchronously on the next run loop cycle; This is probably still before the data has been fetched.
However, even if the data has been fetched, it won't show up because you are assigning userFeedPosts
from a second instance of your API object to AA
at initialisation time. This array is empty and will remain empty since Swift arrays are value types, not reference types. When userFeedPosts
is updated, AA
will hold the original empty array.
To load the data you need to
- Start a load operation when the view loads
- Pass a completion handler to that load operation to be invoked when the load is complete
- Reload your table view with the new data
class EntertainmentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var data = [EntertainmentPageData]()
@IBOutlet weak var entPostTableView: UITableView!
override func viewDidLoad() {
entPostTableView.register(EntertainmentViewrTableViewCell.nib(), forCellReuseIdentifier: EntertainmentViewrTableViewCell.identifier)
entPostTableView.delegate = self
entPostTableView.dataSource = self
super.viewDidLoad()
EntertainmentAPI.getFeedPosts { result in
DispatchQueue.main.async { // Ensure UI updates on main queue
switch result {
case .error(let error):
print("There was an error: \(error)")
case .success(let data):
self.data = data
self.entPostTableView.reloadData
}
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let customCell1 = tableView.dequeueReusableCell(withIdentifier: EntertainmentViewrTableViewCell.identifier, for: indexPath) as! EntertainmentViewrTableViewCell
let post = data[indexPath.row)
customCell1.profileDisplayName.text = data[indexPath.row].postDisplayName
customCell1.configure(with: post.postDisplayName, PostImage: post.imageURLString, PostDescription: post.postDescription)
return customCell1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
public class EntertainmentAPI {
static func getFeedPosts(completion: @escaping ((Result<[EntertainmentPageData],Error>) -> Void) ) {
guard let apiURL = URL(string: "https://api.quickques.com/....") else {
return
}
let task = URLSession.shared.dataTask(with: apiURL) { data, apiResponse, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else {
/// TODO - Invoke the completion handler with a .failure case
return
}
do {
let entPostData = try JSONDecoder().decode([EntertainmentPageData].self, from: Data)
completion(.success(entPostData))
}
catch {
completion(.failure(error))
}
}.resume()
}
}
How do I pass my json data to table views and other view controllers?
You should take 3 viewcontroller
1. HomeViewController: You show only season listing data (Using tableview datasource and delegate )
EpisodesViewController: If user select any row like user just select any Season, then you can also show the all Episodes of that season, you should pass that data from HomeViewController to EpisodesViewController
EpisodesDetailsViewController :
If any Episode is selected then you should send only the details json data
from EpisodesViewController to EpisodesDetailsViewController
And you just show data in this page
This is the steps you have to follow
If you have any problem, please comment here
my email id is : sudebsarkar21@gmail.com, contact here
Pass Json response from one Viewcontroller to another Viewcontroller and populate CollectionView
You need to present it inside the callback of the URLSession.shared.dataTask
like
DispatchQueue.main.async {
self.arrayDrinks.append(response.drinks)
let destinationVC = DrinksListCollectionViewController()
destinationVC.remoteArray = response.drinks
print("print array drink \(destinationVC.remoteArray)")
self.present(destinationVC,animated:true,completion:nil)
}
If it's a segue then replace above with ( also inside the completion )
DispatchQueue.main.async {
performSegue(withIdentifier: "InglistSegue", sender: response.drinks)
}
Add this method
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! DrinksListCollectionViewController
destinationVC.remoteArray = sender as! [Model] // model it type of drinks
}
Related Topics
Swiftui: Stop an Animation That Repeats Forever
Swift - Associated Value or Extension for an Enum
From Which Direction Swift Starts to Read Dictionaries
How to Add Nil Value to Swift Dictionary
Send Keyevent to a Target Window via Process Id
Differencebetween Sequencetype and Collectiontype in Swift
How to Disambiguate a Foreach Loop in Xcode with Swiftui
Swift Crash "Exc_Breakpoint 0X0000000... "
Check If the Username Exist in Firebase
Getting Pixel Format from Cgimage
How to Deal with Commas When Writing Objects to CSV in Swift
Swift How to Format a Large Number with Thousands Separators
Why Does the Completion Handler Does Not Return Anything
Getting Data Out of Completionhandler in Swift in Nsurlconnection
Swift Catch Enum Case with Binding
Initializer for Conditional Binding Must Have Optional Type, Not '[String:Any]'