我正在使用这个Ray Wenderlich tutorial作为我正在进行的项目的指南。但是,我正在尝试扩展此模板以合并子目录、子目录、子子子目录等。
例如,如果您在主/主目录屏幕中单击“Candy Cane”单元格,它将带您进入一个带有表视图的“新”视图控制器(也称为子目录屏幕),该控制器将显示各种Candy Cane供应商及其价格是贵是便宜(这将是每行的副标题)。请参见subCategory。。。下面是txt文件。
在这篇文章中,我使用了category和directory这两个词。
这是第一个陷阱。在过去,我做了一个这样的项目,但我通过许多情节串连板和视图控制器文件为每个我导航的子类别。同样的原则也适用于从子类别移动到子类别屏幕等等。
我不想做广告:但具体来说,我正在开发的应用程序名为iEngineering,它在AppStore上是免费的。请参阅应用程序的库部分,因为我相信它将为理解我的最终目标提供额外帮助。请记住,应用程序的当前版本是使用无数的脚本和视图控制器文件构建的,每次我在Xcode中运行模拟器时都必须构建这些文件。查看显示库功能的应用程序屏幕截图就足够了,无需下载应用程序。
这是第二个陷阱。我在这个应用程序中也有子类别等等。例如,如果单击子类别屏幕中显示甘蔗糖供应商和价格列表的单元格,它将导航到新屏幕(子类别)以显示特定供应商销售的所有不同甘蔗糖。因此,在下面的“my made up”文本文件中,subCandyCaneTextFile.txt,如果您要单击标签为“Candy Cane King”的单元格,它将带您进入显示“Candy Cane King”作为导航标题的屏幕,并显示/加载一个列表(通过读取文本文件导入),其中显示Candy Cane King提供的所有Candy Cane。我没有提供这个和其他txt文件,我认为是子类别。我希望大家记住这一点,因为当我在下面问我问题的根源/核心时。
对于这个项目,我想从使用多个脚本和多个视图控制器。这是因为我以前的项目每次在模拟器中编译/构建都需要大约5到10分钟。因此,我试图在项目运行时读取应用程序中每个新/类别屏幕的文本文件。我希望这能让我跑得更快(大约10秒)。
在下面的示例中,category/main view控制器通过读取txt文件来显示其数据candyTextFile.txt
我的问题是:如何在子类别屏幕的新数据中继续(从|删除)旧数据和(加载|替换)?我曾想过尝试将其作为Ray Wenderlich tutorial教程中的详细视图控制器屏幕;但是,我不确定如何导航到子类别屏幕。因此,我认为我的另一个选择可能是反复使用一个视图控制器和UITableView(主视图控制器)。我不确定该怎么做,因为我对学习Swift和Xcode还比较陌生。
本文的current project via Xcode概述。
在我的MasterViewController.swift中,

    import UIKit

    class MasterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    // MARK: - Properties
    @IBOutlet var tableView: UITableView!
    @IBOutlet var searchFooter: SearchFooter!

    var detailViewController: DetailViewController? = nil

    var candies = [Candy]()
    var filteredCandies = [Candy]()

    let searchController = UISearchController(searchResultsController: nil)

    // MARK: - View Setup
    override func viewDidLoad() {
    super.viewDidLoad()

    // Setup the Search Controller
    searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
    searchController.searchBar.placeholder = "Search Candies"
    navigationItem.searchController = searchController
    definesPresentationContext = true

    // Setup the Scope Bar
    searchController.searchBar.scopeButtonTitles = ["All", "Chocolate","Hard", "Other"]
    searchController.searchBar.delegate = self

    // Setup the search footer
    tableView.tableFooterView = searchFooter


    setupArray()



    if let splitViewController = splitViewController {
        let controllers = splitViewController.viewControllers
        detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
    }

    }


    private func setupArray() {
        if let filepath = Bundle.main.path(forResource: "candyTextFile", ofType: "txt") {
            do {
                let contents = try String(contentsOfFile: filepath)
                let lines_separatedBy_n : [String] = contents.components(separatedBy: "\n")
                let string = lines_separatedBy_n.map { String($0) }.joined(separator: ", ")
                var lines_separatedBy_comma : [String] = string.components(separatedBy: ", ")

                // I've put this in to remove the last bit of the file that was causing the count to be one too high.
                // I'm guessing that's why you had something similar previously?
                lines_separatedBy_comma.removeLast()

                for (index, element) in lines_separatedBy_comma.enumerated() {
                    if index % 2 == 0 {
                        let newCategory = element
                        let newName = lines_separatedBy_comma[index + 1]
                        let newCandy = Candy(category: newCategory, name: newName)
                        candies.append(newCandy)
                    }
                }
                for candy in candies {
                    print("category: \(candy.category), name: \(candy.name)")
                }
                //("\ncandies: \(candies)")
            } catch let error as NSError {
                print(error.localizedDescription)
            }
        }

            print("\ncandies: \(candies)")

    }

    override func viewWillAppear(_ animated: Bool) {
    print("splitViewController!.isCollapsed: \(splitViewController!.isCollapsed)")

    if splitViewController!.isCollapsed {
      if let selectionIndexPath = tableView.indexPathForSelectedRow {
        tableView.deselectRow(at: selectionIndexPath, animated: animated)
      }
    }
    super.viewWillAppear(animated)
    }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    }

    // MARK: - Table View
    func numberOfSections(in tableView: UITableView) -> Int {
    return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if isFiltering() {
        print("Is filtering")
        searchFooter.setIsFilteringToShow(filteredItemCount: filteredCandies.count, of: candies.count)
        return filteredCandies.count
    }
    print("Is not filtering")
    searchFooter.setNotFiltering()
    return candies.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    let candy: Candy
    if isFiltering() {
        candy = filteredCandies[indexPath.row]
    } else {
        candy = candies[indexPath.row]
    }
    cell.textLabel!.text = candy.name
    cell.detailTextLabel!.text = candy.category
    return cell
    }

    // MARK: - Segues
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showDetail" {
            if let indexPath = tableView.indexPathForSelectedRow {
                let candy: Candy
                if isFiltering() {
                    candy = filteredCandies[indexPath.row]
                } else {
                    candy = candies[indexPath.row]
                }
                let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
                controller.detailCandy = candy
                controller.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
                controller.navigationItem.leftItemsSupplementBackButton = true
            }
        }
    }

    func filterContentForSearchText(_ searchText: String, scope: String = "All") {


        filteredCandies = candies.filter({
            (candy : Candy) -> Bool in
        let doesCategoryMatch = (scope == "All") || (candy.category == scope)
            if searchBarIsEmpty(){
                return doesCategoryMatch
            }else {
                return doesCategoryMatch && candy.name.lowercased().contains(searchText.lowercased())

            }
        })

        tableView.reloadData()
    }


    func searchBarIsEmpty() -> Bool {
        return searchController.searchBar.text?.isEmpty ?? true
    }

    func isFiltering() -> Bool {
        let searchBarScoperIsFiltering = searchController.searchBar.selectedScopeButtonIndex != 0
        return searchController.isActive && (!searchBarIsEmpty() || searchBarScoperIsFiltering)
    }


    }

    extension MasterViewController: UISearchBarDelegate {
    // MARK: - UISearchBar Delegate
    func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
        filterContentForSearchText(searchBar.text!, scope: searchBar.scopeButtonTitles![selectedScope])
    }

    }

    extension MasterViewController: UISearchResultsUpdating {
    // MARK: - UISearchBar Delegate
    func updateSearchResults(for searchController: UISearchController) {
        let searchBar = searchController.searchBar
        let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
        filterContentForSearchText(searchController.searchBar.text!, scope: scope)
    }
    }

在candyTextFile.txt中,
Chocolate, Chocolate Bar
Chocolate, Chocolate Chip
Chocolate, Dark Chocolate
Hard, Lollipop
Hard, Candy Cane
Hard, Jaw Breaker
Other, Caramel
Other, Sour Chew
Other, Gummi Bear
Other, Candy Floss
Chocolate, Chocolate Coin
Chocolate, Chocolate Egg
Other, Jelly Beans
Other, Liquorice
Hard, Toffee Apple

在subCandyCaneTextFile.txt中,
Cheap, Brachs
Expensive, Spangler
Expensive, Bobs
Cheap, Candy Cane King
Expensive, Jelly Belly

其他,子类别,文件:
在subDarkChocolateTextFile.txt中,
Cheap, Ghirardelli
Expensive, Dove
Expensive, Lindt
Cheap, Hersheys
Expensive, Hu Dark

在subcollipoptextfile.txt中,
Cheap, Zollipops
Cheap, YumEarth
Expensive, Dum Dums

感谢你们的时间和你们能提供的任何指导。我非常感激。

最佳答案

您可以从同一个脚本中重用DetailViewController。将Storyboard ID分配给它,然后可以从当前实例创建DetailViewController类的新实例。您可以保留新VC的索引,例如递增索引,并使用它从预定义数组中获取下一个类别文件名,并将其加载到viewDidLoad
DetailViewController类中:

    var index = 0;

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let st = UIStoryboard(name: "Main", bundle: nil)
        let vc = st.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
        vc.index = self.index + 1;
        self.navigationController?.pushViewController(vc, animated: true)
    }

ios - 在主从应用程序中为主/从 View  Controller 重用UIViewController(与UITableView一起使用)?-LMLPHP
编辑
如何使用索引
使用文件名声明数组:let files = ["file1", "file2", "file3"]
使用它
if let filepath = Bundle.main.path(forResource: files[index], ofType: "txt")

08-08 02:12