我正在编写一个在每个其他屏幕中都包含网络调用的应用程序。调用的结果将是特定屏幕的数据源。
问题是,我应该在父 viewController 中进行网络调用并在推送当前 viewController 之前注入数据还是推送 currentViewController 并在 viewDidLoad()/viewWillAppear() 上进行网络调用?
这两种方法对我来说都很有意义。
我正在编写一个在每个其他屏幕中都包含网络调用的应用程序。调用的结果将是特定屏幕的数据源。
问题是,我应该在父 viewController 中进行网络调用并在推送当前 viewController 之前注入数据还是推送 currentViewController 并在 viewDidLoad()/viewWillAppear() 上进行网络调用?
这两种方法对我来说都很有意义。
您向网络发出请求的位置实际上应该没有区别。您正在请求一些数据,您将不得不等待并呈现它。您的问题是您应该在哪里等待接收数据。
正如@Scriptable 已经提到的,您可以执行两者中的任何一个。使用哪个取决于您希望拥有什么样的用户体验。这因情况而异,但通常当我们创建资源时,我们通常在当前屏幕上等待它,而当我们读取资源时,我们在下一个屏幕上等待它:
还有其他一些事情需要考虑,因为对于第二种情况,您可以添加更多功能,例如数据缓存。例如,许多消息传递应用程序会将您的聊天记录保存在本地,一旦您按下某个聊天线程,您将直接导航到查看缓存的内容,并且在加载和显示一些新消息后您可能会看到。
因此,如果我们回到您应该“调用”请求的位置,那么使用所有这些似乎您最好在显示新控制器之前或同时这样做。同时,我的意思是将其称为前一个视图控制器上的负载,但在收到新数据之前加载新的视图控制器。
如何做到这一点最好是拥有一个数据模型。考虑这样的事情:
class UsersModel {
private(set) var users: [User]?
}
对于用户,我们只需要一个列表,所以我所做的只是包装了一个数组。因此,在您的情况下,我们应该可以选择加载这些用户:
extension UsersModel {
func fetchUsers() {
User.fetchAll { users, error in
self.users = users
self.error = error // A new property needed
}
}
}
现在添加了一个加载用户并将其分配给内部属性的方法。这足以满足我们在第一个视图控制器中的需要:
func goToUsers() {
let controller = UserListViewController()
let model = UserModel()
controller.model = model
model.fetchUsers()
navigationController.push(controller...
}
现在,我们需要在第二个视图控制器内部建立通信。显然我们需要在刷新时viewDidLoad
才会出现视图。但是我们还需要一些委托(或其他类型的连接),以便我们的视图控制器收到更改的通知:
func viewDidLoad() {
super.viewDidLoad()
self.refreshList()
self.model.delegate = self
}
在刷新时,我们现在应该拥有所需的所有数据:
func refreshList() {
guard let model = model else {
// TODO: no model? This looks like a developer bug
return
}
if let users = model.users {
self.users = users
tableView?.reloadData()
if users.count.isEmpty {
if let error = model.error {
// TODO: show error screen
} else {
// TODO: show no data screen
}
}
} else {
// TODO: show loading indicator screen
}
}
现在这里需要做的就是用委托完成模型:
extension UsersModel {
func fetchUsers() {
User.fetchAll { users, error in
self.users = users
self.error = error // A new property needed
self.delegate?.usersModel(self, didUpdateUsers: self.users)
}
}
}
视图控制器简单地实现了:
func usersModel(_ sender: UserModel, didUpdateUsers users: [User]?) {
refreshList()
}
现在我希望你能想象这样一个系统的美妙之处,例如你的模型可以首先从一些本地缓存或数据库异步加载用户并调用委托,然后将请求调用到服务器并再次调用委托,而你的视图控制器会显示适用于任何情况的数据。