【问题标题】:Swift - access array from another ViewControllerSwift - 从另一个 ViewController 访问数组
【发布时间】:2020-11-04 23:35:22
【问题描述】:

在 FilterViewController 中,我有“applyButtonClicked”方法,该方法会在按钮单击时触发。在此方法中,我填写并获取要在 ViewController 文件中使用的“selectedCtgsArr”数组。

当 selectedCtgsArr 数组已被填充(applyButtonClicked 方法启动)时,如何将 selectedCtgsArr 的值从 FilterViewController 复制到 ViewController 中的 selectedCategoriesArr?

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()
    }
}

视图控制器:

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()
    }
}

【问题讨论】:

标签: ios arrays swift class viewcontroller


【解决方案1】:

有以下三种方法:

1- 如果两个视图控制器之间存在连接,则使用功能准备 segue 使用程序化 segue。

2- 在过滤视图控制器中使用协议

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
    }
}

在视图控制器中

class ViewController: UIViewController {
    var filter: FilterViewProtocol!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        loadAllCategories()
        
        var selectedCategoriesArr: [String] = filter.selectedCatgry
        
    }
}

3- 使用静态变量,但不推荐使用此方法 在过滤视图控制器中

class FilterViewController: UIViewController {
    
    var categories = [Category]()
    
    var output = [[String : Any]]()
    
    var static selectedCtgsArr = [String]()
}

在视图控制器中

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        loadAllCategories()
        
        var selectedCategoriesArr: [String] = FilterViewController.selectedCtgsArr
        
    }
}

【讨论】:

  • 谢谢。我使用了第二个选项,但它失败了,因为当我进入 ViewController 时 selectedCategoriesArr 为 nil,因为我还没有进入 FilterViewController 并单击了“应用按钮”。我该如何解决? i.stack.imgur.com/xpdP3.jpg
  • 添加if语句检查filter vc中访问的数组是否为空
  • 遇到同样的问题i.stack.imgur.com/FEtrI.jpg
【解决方案2】:

根据 Apple 在Using Segues 上的指南

源视图控制器的 prepareForSegue:sender: 方法让 您将数据从源视图控制器传递到目标视图 控制器。传递给该方法的 UIStoryboardSegue 对象包含 对目标视图控制器的引用以及其他 segue 相关信息。

这看起来通常是这样的模式

public override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? TypeOfViewControllerBeingShown {
        destination.someMethodAcceptingData(dataToShare)
    }
}

你传递你想要的任何数据,目标视图控制器会做任何它需要的事情。所有这些都发生在目标视图控制器出现在屏幕上之前,因此它可以将此信息用于所需的任何设置/配置。

【讨论】:

  • 我创建了一个方法 - i.stack.imgur.com/mOKya.png。从 ViewController 到 FilterViewController 的命名 segue - filtersSegue.Added performSegue(withIdentifier: "filtersSegue", sender: self) 在 applyButtonClicked() 方法的末尾。但是当我单击“应用”按钮时出现错误,它显示“异常:”接收器()没有标识符为“filtersSegue”的segue”“
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-24
  • 2015-06-16
  • 1970-01-01
  • 2014-10-18
  • 2012-02-26
  • 1970-01-01
相关资源
最近更新 更多