Reputation: 9
In FilterViewController I have "applyButtonClicked" method that fires up on button click. In this method I fill in and get "selectedCtgsArr" array that I want to use in ViewController file.
How can I copy the value of the selectedCtgsArr from the FilterViewController to the selectedCategoriesArr from the ViewController when selectedCtgsArr array is already filled (applyButtonClicked method fired up)?
FilterViewController:
class FilterViewController: UIViewController {
var categories = [Category]()
var output = [[String : Any]]()
var selectedCtgsArr = [String]()
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var applyButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
getCategories()
}
@IBAction func applyButtonClicked(_ sender: UIButton) {
var selectedCatgry = [String]()
for i in 0..<output.count {
let rowVal = output[i]
if rowVal["status"] as! String == "1"{
selectedCatgry.append(rowVal["name"] as! String)
}
}
selectedCtgsArr = selectedCatgry
print(selectedCtgsArr) // copy this array
}
func getCategories() {
let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/list.php?c=list")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error == nil {
do {
self.categories = try JSONDecoder().decode(Categories.self, from: data!).drinks
for i in 0..<self.categories.count {
self.output.append(["name":self.categories[i].strCategory, "status":"1"])
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print(error)
}
}
}.resume()
}
}
ViewController:
class ViewController: UIViewController {
var drinks = [Drink]()
var categories = [OneCategory]()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
loadAllCategories()
var selectedCategoriesArr: [String] = [] // copy here
}
func loadAllCategories() {
let url = URL(string: "https://www.thecocktaildb.com/api/json/v1/1/list.php?c=list")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if let error = error {
print(error)
return
}
do {
let result = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
let categoryNames = (result["drinks"] as! [[String:String]]).map{$0["strCategory"]!}
let group = DispatchGroup()
for category in categoryNames {
let categoryURLString = "https://www.thecocktaildb.com/api/json/v1/1/filter.php?c=\(category)"
.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let categoryURL = URL(string: categoryURLString)!
group.enter()
let categoryTask = URLSession.shared.dataTask(with: categoryURL) { (categoryData, _, categoryError) in
defer {
group.leave()
}
if let categoryError = categoryError {
print(categoryError)
return
}
do {
let drinks = try JSONDecoder().decode(Response.self, from: categoryData!).drinks
self.categories.append(OneCategory(name: category, drinks: drinks))
} catch {
print(error)
}
}
categoryTask.resume()
}
group.notify(queue: .main) {
self.tableView.reloadData()
}
} catch {
print(error)
}
}.resume()
}
}
Upvotes: 0
Views: 958
Reputation: 21
There are three ways to do so:
1- Using programatic segue using function prepare for segue if there's connection between the two view controllers.
2- Using Protocols in the filter view controller
protocol FilterViewProtocol: AnyObject {
var selectedCatgry: [String] {get}
}
class FilterViewController: UIViewController {
var categories = [Category]()
var output = [[String : Any]]()
var selectedCtgsArr = [String]()
var selectedCatgry: [String] {
return selectedCtgsArr
}
}
in the view controller
class ViewController: UIViewController {
var filter: FilterViewProtocol!
override func viewDidLoad() {
super.viewDidLoad()
loadAllCategories()
var selectedCategoriesArr: [String] = filter.selectedCatgry
}
}
3- using static variable however this method is not recommended in filter view controller
class FilterViewController: UIViewController {
var categories = [Category]()
var output = [[String : Any]]()
var static selectedCtgsArr = [String]()
}
in view controller
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
loadAllCategories()
var selectedCategoriesArr: [String] = FilterViewController.selectedCtgsArr
}
}
Upvotes: 1
Reputation: 22325
According to Apple's guide on Using Segues
The prepareForSegue:sender: method of the source view controller lets you pass data from the source view controller to the destination view controller. The UIStoryboardSegue object passed to the method contains a reference to the destination view controller along with other segue-related information.
What this looks like is usually a pattern like this
public override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? TypeOfViewControllerBeingShown {
destination.someMethodAcceptingData(dataToShare)
}
}
you pass whatever data you want and the destination view controller does whatever it needs to with it. All of this happens before the destination view controller appears on screen so it can use this information to any setup/configuration needed.
Upvotes: 0