等待JSON在不同的类文件中快速解析3
我创建了一个类,如下面的代码所示,并且您可以看到我正在解析viewController之外的类中的JSON文件。等待JSON在不同的类文件中快速解析3
当我在视图控制器中创建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.
}
}
1)如果您是通过UIStoryboard赛格瑞传递一个对象,它是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一起使用,因此如果您需要本地存储,请记住这一点。
到底,你应该能够建立的卡什么的数组是这样的:
APIClient.shared.fetchCards(completion: { cardJSONs in
let cards = [Card]()
for cardJSON: JSON in cardJSONs {
let card = Card(from; JSON)
cards.append(card)
}
}
下面是完成处理的一个例子。 首先,你必须写在一个类中的前一个函数: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)
})
*不要问,告诉*。既然你只有**一个任务,一个派遣组是没用的。使用完成处理程序通知主叫方下载和分析已完成。并使用专用的后台线程来避免冻结或在单独的功能中调用下载任务。 – vadian
我该怎么做? – aspnet82
这里有数百个相关的问题,请搜索例如https://*.com/search?q=%5Bswift%5D+completion+handler – vadian