簡體   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