繁体   English   中英

在Swift 3中等待在其他类文件中进行JSON解析

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM