gpt4 book ai didi

swift - 通过移走 TableView 使 ViewController 更 slim

转载 作者:搜寻专家 更新时间:2023-11-01 06:50:40 31 4
gpt4 key购买 nike

我是编程新手,在尝试通过将 tableView 和关联 View 的创建移动到单独的类并将委托(delegate)和数据源从 VC 移动到单独的类来精简我的 ViewController 时遇到了一些问题。

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

  • 网络连接后,当接收到数据时,我在闭包类中调用以设置将嵌入 UITableView 的 View 。
  • 获取的数据正在保存到 CoreData 栈中

我从另一个类实例化 View

var detailView: DetailView! { return self.view as? DetailView }

一旦我将下载 UI 的第一部分(单独调用效果很好)

我正在转向凌乱且超出我能力的部分

我调用函数 createReposCard()

        dispatchGroup.notify(queue: dispatchQueue) {
DispatchQueue.main.async {

// slide animation
UIView.animate(withDuration: 0.75, delay: 0.5, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.0, options: [], animations: {
self.detailView.reposCard.center = CGPoint(x: self.detailView.reposCard.center.x, y: self.detailView.reposCard.center.y-UIScreen.main.bounds.height)
}, completion: nil)
self.detailView.createReposCard(for: self.repos)
self.detailView.detailsTableView.reloadData()
self.activityIndicator.stopAnimating()
self.activityIndicator.removeFromSuperview()
}
}

代码不完整,只能描述问题,具体做了什么一一说明。我正在传递有关选定用户的信息(无关信息)然后我正在引用我的 DetailsViewController,它仍然是例如持有 CoreData 栈

在初始化程序中,我正在实例化 detailsViewController 并将其传递给持有委托(delegate)的类(我将其传递给那里有对 CoreData 的引用)

class DetailView: UIView {


var selectedUser: User?


var detailsViewController: DetailsViewController!


let detailsTableView: UITableView = {
let tableView = UITableView()
tableView.frame = CGRect.zero
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "reposCell")
return tableView
}()

init(selectedUser:User, frame: CGRect) {
super.init(frame: frame)
self.selectedUser = selectedUser

detailsViewController = DetailsViewController()
let tableViewDelegates = TableViewDelegates(detailsViewController: detailsViewController)
detailsTableView.delegate = tableViewDelegates
detailsTableView.dataSource = tableViewDelegates
}

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

public class TableViewDelegates: NSObject, UITableViewDataSource,UITableViewDelegate {

private let detailsViewController: DetailsViewController

init(detailsViewController: DetailsViewController){
self.detailsViewController = detailsViewController
super.init()
}

public func numberOfSections(in tableView: UITableView) -> Int {
return detailsViewController.fetchedResultsController.sections?.count ?? 1

}
...

其实我也不知道自己的概念好不好,感觉很迷茫,但我的初衷是这样的:

  • 将 View 创建移至其他类
  • 将 TableView 代理移至其他类最后 - 将网络和 CoreData 移动到其他类。

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

最佳答案

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

1)为什么我的变量在解包时是nil?

我认为我们没有足够的信息来准确回答这个问题,但我的总体方法是这样的:

  1. 检查正在解包的 nil 变量;
  2. 确保此变量已正确初始化;
  3. 确保对象没有被错误地取消初始化;
  4. 如果您使用的是 Storyboard,请使用检查器检查所有设置是否正确。

关于第 2 步有一个特别的观察:您应该检查方法的执行顺序以确保变量被正确初始化。我为什么要强调这一点?因为某些 View (例如 detailView)有可能像普通的 UIView 一样被初始化, 然后您尝试访问不属于 的元素UIView 对象(例如,表格 View )。换句话说,在尝试访问它们之前检查您是否设置了自定义 View 。

2) 如何以更有条理的方式构建项目?

这是一个更有趣的问题,我认为选择更好的方法将帮助您避免遇到类似您遇到的问题。我将把它分成一些主题。这里的所有内容都是我的个人意见,不一定反射(reflect)最佳方法,尤其是因为这里的“最佳”是主观的。

PersistenceManager 类

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

在某些架构中(例如,VIPER), View Controller 直接访问持久性是不正确的,因此传递一个已获取对象的数组会更合适。例如:

class TableViewController {
private let tableView: UITableView!
private var currentlyDisplayedUsers: [Users]?

func displayUsers(_ users: [Users]) {
self.currentlyDisplayedUsers = users
self.tableView.reloadData()
}
}

在上面的示例中,tableView 将显示 currentlyDisplayedUsers,这将由方法 displayUsers 更新,该方法将被某人调用否则,就像演示者一样。

网络类

其次,我认为你应该有一个网络类来从互联网上下载数据。您将在应用程序逻辑中使用 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
}
}
}

TableView、TableViewDelegate 和 TableViewDataSource

最后,如何组织这些家伙。 UITableViewDelegate 负责告诉我们表中的事件,而 UITableViewDataSource 负责用数据填充表,这意味着两者都与 TableView 本身密切相关。也就是说,恕我直言,两者都应该在不同的 swift 文件中实现,但作为具有对 TableView 的引用的 View Controller 的扩展。有点像

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

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

使用这种方法,委托(delegate)和数据源可以访问前面提到的 users 数组。 Here是如何使用 VIPER 实现类似方法的示例。


所以,我希望我能提供有关这些主题的基本概念。如果您想了解更多有关如何构建代码的信息,我建议您研究 iOS 设计模式和架构模式。 iOS 开发中一些著名的架构设计模式是 MVC、MVP、MVVM 和 VIPER。

关于swift - 通过移走 TableView 使 ViewController 更 slim ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57595878/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com