2017-06-20 68 views
-1

我創建了一個類,如下面的代碼所示,並且您可以看到我正在解析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. 
} 


} 
+0

*不要問,告訴*。既然你只有**一個任務,一個派遣組是沒用的。使用完成處理程序通知主叫方下載和分析已完成。並使用專用的後臺線程來避免凍結或在單獨的功能中調用下載任務。 – vadian

+0

我該怎麼做? – aspnet82

+0

這裏有數百個相關的問題,請搜索例如https://stackoverflow.com/search?q=%5Bswift%5D+completion+handler – vadian

回答

0

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) 
    } 
} 
2

下面是完成處理的一個例子。 首先,你必須寫在一個類中的前一個函數: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) 
})