我正在创建一个应用程序并完成所有逻辑,但我想进行代码重构并创建MVC模式。但是我处理的是来自API的一些异步信息。
/ MenuViewController
Alamofire.request(.GET, Urls.menu).responseJSON { request in
if let json = request.result.value {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
let data = JSON(json)
var product: [Product] = []
for (_, subJson): (String, JSON) in data {
product += [Product(id: subJson["id"].int!, name: subJson["name"].string!, description: subJson["description"].string!, price: subJson["price"].doubleValue)]
}
dispatch_async(dispatch_get_main_queue()) {
self.products += product
self.tableView.reloadData()
}
}
}
}
这是我的代码,已经有效了。但我想创建一个Model来处理这个问题,然后将Products数组返回给我的MenuViewController。
型号/菜单
class Menu {
var products: [Product] = []
init() {
Alamofire.request(.GET, Urls.menu).responseJSON { request in
if let json = request.result.value {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
let data = JSON(json)
var product: [Product] = []
for (_, subJson): (String, JSON) in data {
product += [Product(id: subJson["id"].int!, name: subJson["name"].string!, description: subJson["description"].string!, price: subJson["price"].doubleValue)]
}
dispatch_async(dispatch_get_main_queue()) {
self.products += product
}
}
}
}
}
func totalOfProducts() -> Int {
return self.products.count
}
func getProducts() -> [Product]? {
return self.products
}
func getProductFromIndex(index: Int) -> Product {
return self.products[index]
}
}
但是我有了自我思考,我将如何将main_queue送到另一个班级?
所以我尝试过这样的事情:
class MenuViewControlvar: UITableViewController {
var products: [Product] = []
let menu: Menu = Menu()
// MARK: View Controller Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
if let products = menu.getProducts() {
self.tableView.reloadData()
}
// rest of the code
但没有奏效。我的TableView永远不会更新。
我想知道我是否可以这样做,或者我要将我的Alamofire代码保存在我的viewDidLoad()
我的 MenuViewController
谢谢。
答案 0 :(得分:2)
我只是给你一个方向,我将遵循的步骤(不写代码,认为你可以解决):
首先,编写一个接受网络请求和竞争块的网络类。完成网络后,应立即执行完成块。这是一个包装类,可以跨类使用。
其次,编写一个模型类,其中包含视图控制器功能/视图绘制所需的所有参数。
来自视图控制器的第三,,调用网络类。在完成块中,传递模型设置,表重新加载代码和任何代码以删除加载覆盖/指示符。该块应该在主队列上执行。
第四,在触发网络之前添加代码以显示加载覆盖/指示符。
答案 1 :(得分:1)
委派是针对基于异步网络调用更新模型数据和视图的问题的理想解决方案,这与在整个iOS SDK中实现的解决方法非常相似问题。授权优于观察有许多好处,这是另一种可行的解决方案。
首先,将您的网络代码移至单独的类
class NetworkingController {
创建视图控制器可以符合的协议。这提供了网络操作和视图之间的松散耦合,以有效地保持MVC层之间的分离。
@protocol NetworkingControllerDelegate: class {
func menuDataDidUpdate()
}
让网络控制器支持其代理的属性
weak var delegate: NetworkingControllerDelegate?
总之,您的网络类现在看起来像这样:
@protocol NetworkingControllerDelegate: class {
func menuDataDidUpdate()
}
class NetworkingController {
weak var delegate: NetworkingControllerDelegate?
// Insert networking functions here.
}
然后,让您的视图控制器符合此协议
class MenuViewController: NetworkingControllerDelegate {
在视图控制器中创建一个新的网络控制器
var myNetworkController = NetworkController()
并将网络控制器实例的委托设置为视图控制器
myNetworkController.delegate = self
然后在您的网络代码中,当网络请求完成并且您的模型已更新时,请拨打网络控制器的代表。
delegate.menuDidUpdate()
在视图控制器中为此方法创建实现,因为它现在是网络代码的委托。
func menuDidUpdate() {
// Update your menu.
}
这使您的视图控制器看起来像:
class MenuViewController: NetworkingControllerDelegate {
var myNetworkController = NetworkController()
override func viewDidLoad() {
myNetworkController.delegate = self
}
// MARK: NetworkingControllerDelegate
func menuDidUpdate() {
// Update your menu.
}
}
这只是实现的大纲,为您提供有关如何继续的必要信息。完全适应您的问题取决于您。