Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 通过移开TableView使ViewController更纤细_Swift_Uitableview - Fatal编程技术网

Swift 通过移开TableView使ViewController更纤细

Swift 通过移开TableView使ViewController更纤细,swift,uitableview,Swift,Uitableview,我对编程非常陌生,在尝试通过将tableView和关联视图的创建移动到单独的类以及将委托和数据源从VC移动到单独的类来精简ViewController时,我遇到了一些问题 我目前的文件和工作如下: 在网络连接之后,当接收到数据时,我在一个闭包类中调用,以设置具有嵌入式UITableView的视图 获取的数据正在保存到CoreData堆栈中 我从另一个类实例化视图 var detailView: DetailView! { return self.view as? DetailView }

我对编程非常陌生,在尝试通过将tableView和关联视图的创建移动到单独的类以及将委托和数据源从VC移动到单独的类来精简ViewController时,我遇到了一些问题

我目前的文件和工作如下:

  • 在网络连接之后,当接收到数据时,我在一个闭包类中调用,以设置具有嵌入式UITableView的视图
  • 获取的数据正在保存到CoreData堆栈中
我从另一个类实例化视图

var detailView: DetailView! { return self.view as? DetailView }
一旦我将下载UI的第一部分(单独调用,效果很好)

我正在进入一个凌乱的、超越我能力的角色

我调用函数createReposCard()

代码不完整,仅描述问题,但它一个接一个地做了什么。 我正在传递有关所选用户的信息(无关信息) 然后我引用了我的DetailsViewController,它仍然保存着CoreData堆栈

在初始化器中,我实例化detailsViewController并将其传递给包含委托的类(我传递它是为了在其中引用CoreData)

最后,代码跳转到所描述的类中,我被“在隐式展开时意外地发现了nil…”打倒了

事实上,我不知道我的想法是否好,因为我感到很失落,但我的意图如下:

  • 将视图创建移动到其他类
  • 将TableView委托移动到其他类 最后-将网络和CoreData移动到其他类

但正如我所见,简单的数据传递正在克服我的能力。

我认为这个问题可以分为两部分:

1) 为什么当我打开变量时它是nil? 我认为我们没有足够的信息来准确回答这个问题,但我的总体方法是:

  • 检查正在展开的nil变量
  • 确保此变量已正确初始化
  • 确保对象没有被错误地去初始化
  • 如果您使用的是故事板,请使用检查器检查所有设置是否正确
  • 关于步骤2有一个特别的观察:您应该检查方法的执行顺序,以确保变量正确初始化。我为什么要强调这一点?因为有可能某些视图(例如,
    detailView
    )像普通的
    UIView一样初始化,
    ,然后您尝试访问不属于
    UIView
    对象的元素(例如,表视图)。换句话说,在尝试访问自定义视图之前,请检查是否正在设置它们

    2) 如何以更有组织的方式组织项目? 这是一个更有趣的问题,我认为选择一个更好的方法将有助于你避免像你所经历的那样的问题。我将把它分成几个主题。这里的一切都是我个人的观点,并不一定反映出最佳方法,特别是因为“最佳”在这里是主观的

    PersistenceManager类

    首先,将视图控制器的引用传递给另一个类只是为了访问CoreData似乎不是一个好的选择。例如,更好的方法是使用
    PersistenceManager
    类。您可以使用此类的对象来获取和保存数据。可以传递此对象而不是视图控制器

    在某些体系结构(例如VIPER)中,视图控制器直接访问持久性是不正确的,因此更适合传递已获取对象的数组。例如:

    class TableViewController {
        private let tableView: UITableView!
        private var currentlyDisplayedUsers: [Users]?
    
        func displayUsers(_ users: [Users]) {
            self.currentlyDisplayedUsers = users
            self.tableView.reloadData()
        }
    }
    
    在上面的示例中,
    tableView
    将显示
    currentlyDisplayedUsers
    ,它将由方法
    displayedusers
    更新,其他人(如演示者)将调用该方法

    网络类

    第二,我认为你应该有一个网络课程来从互联网上下载数据。您将在应用程序逻辑中使用Network类的实例。换句话说,你会有

    // This is in the application logic
    // In MVC, the logic is in the Controller, while in VIPER the logic is in the Interactor
    class ApplicationLogic {
        let networkAPI: Network?
    
        ...
    
        func fetchUserData() {
            networkAPI?.fetchUsers() { data, error in
                // Update the UI based on the response
                // Using the previous example, you could call displayUsers here
            }
        }
    }
    
    // TableViewController+UITableViewDelegate.swift
    extension TableViewController: UITableViewDelegate {
        ...
    }
    
    // TableViewController+UITableViewDataSource.swift
    extension TableViewController: UITableViewDataSource {
        ...
    }
    
    TableView、TableViewDelegate和TableViewDataSource

    最后,如何组织这些人
    UITableViewDelegate
    负责告诉我们表中的事件,而
    UITableViewDataSource
    负责用数据填充表,这意味着两者都与表视图本身密切相关。也就是说,imho应该在不同的swift文件中实现,但是作为对表视图有引用的视图控制器的扩展。差不多

    // This is in the application logic
    // In MVC, the logic is in the Controller, while in VIPER the logic is in the Interactor
    class ApplicationLogic {
        let networkAPI: Network?
    
        ...
    
        func fetchUserData() {
            networkAPI?.fetchUsers() { data, error in
                // Update the UI based on the response
                // Using the previous example, you could call displayUsers here
            }
        }
    }
    
    // TableViewController+UITableViewDelegate.swift
    extension TableViewController: UITableViewDelegate {
        ...
    }
    
    // TableViewController+UITableViewDataSource.swift
    extension TableViewController: UITableViewDataSource {
        ...
    }
    
    使用这种方法,代理和数据源可以访问前面提到的
    users
    数组。是如何使用VIPER实现类似方法的示例


    所以,我希望我能就这些话题提供一个基本的想法。如果您想更多地了解如何构造代码,我建议您研究iOS设计模式和体系结构模式。iOS开发中著名的一些架构设计模式有MVC、MVP、MVVM和VIPER

    // TableViewController+UITableViewDelegate.swift
    extension TableViewController: UITableViewDelegate {
        ...
    }
    
    // TableViewController+UITableViewDataSource.swift
    extension TableViewController: UITableViewDataSource {
        ...
    }