[英]Wait for JSON parsing in a different class file in swift 3
我创建了一个类,如下面的代码所示,您可以看到我正在viewController之外的类中解析一个JSON文件。
当我在视图控制器中创建AllCards对象时,显然在开始时返回0,但过一会儿它返回正确数量的卡。
这是我的问题:
1)如何在viewDidLoad之前等待对象创建,以便在视图加载后,AllCard对象将返回正确数量的卡?
2)如果我在viewController中添加一个按钮来更新卡片数量,它将冻结直到创建所有卡片。 我认为是因为在我的代码中所有内容都在主队列中。 我该如何解决?
3)像我一样在单独的类中解析JSON是一个好习惯吗?
AllCards类:
import Foundation
import Alamofire
import SwiftyJSON
class AllCards {
var allCard = [Card]()
let dispatchGroup = DispatchGroup()
//gzt the JSON with Alamofire request
let allCardsHTTP: String = "https://omgvamp-hearthstone-v1.p.mashape.com/cards?mashape"
init() {
dispatchGroup.enter()
Alamofire.request(allCardsHTTP, method: .get).responseJSON { (response) in
if response.result.isSuccess {
let jsonCards : JSON = JSON(response.value!)
print("success")
//create the cards
if jsonCards["messagge"].stringValue != "" {
print(jsonCards["message"].stringValue)
}
else {
for (set, value) in jsonCards {
if jsonCards[set].count != 0 {
for i in 0...jsonCards[set].count - 1 {
let card = Card(id: jsonCards[set][i]["cardId"].stringValue, name: jsonCards[set][i]["name"].stringValue, cardSet: set, type: jsonCards[set][i]["type"].stringValue, faction: jsonCards[set][i]["faction"].stringValue, rarity: jsonCards[set][i]["rarity"].stringValue, cost: jsonCards[set][i]["cost"].intValue, attack: jsonCards[set][i]["attack"].intValue, durability: jsonCards[set][i]["durability"].intValue, text: jsonCards[set][i]["text"].stringValue, flavor: jsonCards[set][i]["flavor"].stringValue, artist: jsonCards[set][i]["artist"].stringValue, health: jsonCards[set][i]["health"].intValue, collectible: jsonCards[set][i]["collectible"].boolValue, playerClass: jsonCards[set][i]["playerClass"].stringValue, howToGet: jsonCards[set][i]["howToGet"].stringValue, howToGetGold: jsonCards[set][i]["howToGetGold"].stringValue, mechanics: [""], img: jsonCards[set][i]["img"].stringValue, imgGold: jsonCards[set][i]["imgGold"].stringValue, race: jsonCards[set][i]["race"].stringValue, elite: jsonCards[set][i]["elite"].boolValue, locale: jsonCards[set][i]["locale"].stringValue)
if jsonCards[set][i]["mechanics"].count > 0 {
for n in 0...jsonCards[set][i]["mechanics"].count - 1 {
card.mechanics.append(jsonCards[set][i]["mechanics"][n]["name"].stringValue)
}
}
else {
card.mechanics.append("")
}
self.allCard.append(card)
}
}
else {
print("The set \(set) has no cards")
}
}
print(self.allCard.count)
}
}
else {
print("No network")
}
self.dispatchGroup.leave()
}
}
}
视图控制器:
import UIKit
class ViewController: UIViewController {
let allcards = AllCards()
let mygroup = DispatchGroup()
@IBAction func updateBtn(_ sender: Any) {
print(allcards.allCard.count) //Button is frozen until all the cards have been created then it shows the correct number of cards
}
override func viewDidLoad() {
super.viewDidLoad()
print(allcards.allCard.count) / This returns 0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
这是完成处理程序的示例。 首先,您必须在单个类中编写一个函数,例如:APICall
func getDataFromJson(allCardsHTTP: String, completion: @escaping (_ success: Any) -> Void) {
Alamofire.request(allCardsHTTP, method: .get).responseJSON { response in
if response.result.isSuccess {
completion(response)
}
}
}
并从任何类调用此方法。
let callApi = APICall()
callApi.getDataFromJson(allCardsHTTP: "https://omgvamp-hearthstone-v1.p.mashape.com/cards?mashape",completion: { response in
print(response)
})
1)如果通过UIStoryboard segue传递对象,则在调用viewDidLoad()
之前设置该对象。 但是,如果要等待UI元素准备就绪,通常我会在UI元素上使用didSet
,则可以添加guard
语句,如果需要的话可以在其中检查对象。
2)首先,您可能需要关闭,因此请先阅读3)。 如果您在此处使用dispatchGroup.enter()
,则DispatchQueue.global.async { }
是完成您正在执行的操作的常用方法。 如果需要,可以在完成后添加DispatchQueue.main.async { }
,或者真正地由您自己决定进入视图控制器的主线程。 有空的时候看看[unowned self]
和[weak self]
之间的区别。
3)给您的Card
对象一个init(from: JSON)
初始化程序,在其中初始化您要传递的JSON对象的属性。 让负责下载的函数(在您的情况下为Alamofire)生活在另一个类中(例如APIClient
),并为它提供一个下载函数,该函数在参数列表中带有闭包,例如completion: ((JSON?) -> ())?
返回JSON
对象。 让该类下载一个JSON对象,然后使用您先前编写的init(from: JSON)
初始化程序初始化Card
对象。 请注意,这不是适合与Core Data NSManagedObjects一起使用的方法,因此,如果您需要本地存储,请记住这一点。
最后,您应该能够构建如下的Cards数组:
APIClient.shared.fetchCards(completion: { cardJSONs in
let cards = [Card]()
for cardJSON: JSON in cardJSONs {
let card = Card(from; JSON)
cards.append(card)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.