URLSession.dataTask возвращает данные с 0 - PullRequest
0 голосов
/ 02 октября 2018

У меня есть веб-страница для предоставления мне данных сервера в формате JSON, и я пытаюсь добраться до сайта и получить эти объекты.Но данные вернутся с 0;пустая переменнаяМой код выглядит так.

    func downloadItems() {

    let url: URL = URL(string: urlPath)!

    let defaultSession = URLSession(configuration: URLSessionConfiguration.default)

    let task = defaultSession.dataTask(with: url) {
        (data, response, error) in

        if error != nil {
            print("Failed to download data")
        }else {
            let httpResponse = response as? HTTPURLResponse
            print("data is like: \(data as! NSData)")
            print(httpResponse)
            self.data = data!
            print("Data downloaded")
            self.parseJSON(self.data)
        }

    }

    task.resume()
}

func parseJSON(_ data: Data){
    var jsonResult = NSArray()

    do{
        jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as! NSArray
        print(jsonResult)
    } catch let error as NSError {
        print(error)
    }

    var jsonElement = NSDictionary()
    let forest = NSMutableArray()

    for tree in 0 ..< jsonResult.count {

        jsonElement = jsonResult[tree] as! NSDictionary

        let tempTree = trees()

        if let latinName = jsonElement["latin_name"] as? String,
        let turkishName = jsonElement["turkish_name"] as? String,
        let seedType = jsonElement["seed_type"] as? Int,
        let leafType = jsonElement["leaf_type"] as? Int,
        let spreadingArea = jsonElement["spreading_area"] as? String,
        let bothanicalProp = jsonElement["bothanical_prop"] as? String {
            tempTree.latin_name = latinName
            tempTree.turkish_name = turkishName
            tempTree.seed_type = seedType
            tempTree.leaf_type = leafType
            tempTree.spreading_area = spreadingArea
            tempTree.botanical_prop = bothanicalProp
        }

        forest.add(tempTree)

    }

    DispatchQueue.main.async {
        self.delegate.itemsDownloaded(items: forest)
    }

}

, а мой основной контроллер вида выглядит так:

    override func viewDidLoad() {
    super.viewDidLoad()

    //table view delegats and datasource declaration
    treeTableView.delegate = self
    treeTableView.dataSource = self

    let treeModel = trees()
    treeModel.delegate = self
    treeModel.downloadItems(completion: <#T##(Data?) -> Void#>)

}

func itemsDownloaded(items: NSArray) {
    feedTrees = items
    self.treeTableView.reloadData()
}

Когда я захожу на сайт, объект JSON находится здесь.Но когда я попытался получить объект с помощью dataTask.Данные будут 0. Также HTTP Response - 200. Есть ли какие-либо знания об этой ситуации?Спасибо и хорошее кодирование.

print (jsonResult) -

{
    "bothanical_prop" = "T\U00fcrkiyede park ve bah\U00e7elerde dekoratif ama\U00e7la kullan\U0131l\U0131r. Do\U011fal yay\U0131l\U0131\U015f alan\U0131 \U015eili'nin g\U00fcneyi ve G\U00fcnaybat\U0131 Arjantin'deki And Da\U011flar\U0131d\U0131r.";
    "latin_name" = "Araucaria araucana (Molina) K. Koch.";
    "leaf_type" = 1;
    "seed_type" = 1;
    "spreading_area" = "Do\U011fal alanlarda erkekler 15-18 m, di\U015filer ise 30-50 m ye kadar boylanabilir. Park ve bah\U00e7elerde ise 10 m'yi nadiren ge\U00e7en herdemye\U015fil a\U011fa\U00e7lard\U0131r. G\U00f6zvdesi d\U00fczg\U00fcnd\U00fcr; \U00f6zellikle gen\U00e7 bireyleri simetriktir ve konik formludur. Yapraklar\U0131, deri gibi sert, u\U0308\U00e7gen \U015feklinde, u\U00e7lar\U0131 sivri, bat\U0131c\U0131 ve her iki yu\U0308zu\U0308 koyu ye\U015fildir.";
    "turkis_name" = "Maynum \U00c7\U0131kmaz A\U011fac\U0131";
},
    {
    "bothanical_prop" = "Norfolk adalar\U0131na (Avustralya) \U00f6zgu\U0308 endemik bir tu\U0308rdu\U0308r. Dekoratif ama\U00e7l\U0131 \U00fclkemizde Ege, Akdeniz ve Marmara \U00e7evresinde d\U0131\U00e7 mekan bitkisi olarak kullan\U0131l\U0131r.";
    "latin_name" = "Araucaria heterophylla (Salisb.) Franco";
    "leaf_type" = 1;
    "seed_type" = 1;
    "spreading_area" = "60-70 m\U2019ye kadar boylanabilen bir orman a\U011fac\U0131d\U0131r. Dallar g\U00f6vdeden 4-7\U2019li \U00e7evrel olarak \U00e7\U0131kar. G\U00f6vde kabu\U011fu ince levhalar halinde \U00e7atlakl\U0131d\U0131r. Yapraklar\U0131 2 farkl\U0131 \U015fekildedir: Gen\U00e7 ve yan su\U0308rgu\U0308nlerde a\U00e7\U0131k ye\U015fil, biz gibi uzun, k\U00f6\U015feli ve yumu\U015fak; ya\U015fl\U0131 su\U0308rgu\U0308nlerde ise daha k\U0131sa, daha sert, s\U0131k, birbiri u\U0308zerine binmi\U015f ve u\U00e7 k\U0131s\U0131mlar\U0131 boynuz gibi \U00f6ne do\U011fru k\U0131vr\U0131lm\U0131\U015f olan yapraklar vard\U0131r";
    "turkis_name" = "Salon arokaryas\U0131";
}

Ответы [ 4 ]

0 голосов
/ 04 октября 2018

Я исправляю проблему ... Мой код до исправления

override func viewDidLoad() {
    super.viewDidLoad()

    //table view delegats and datasource declaration
    self.treeTableView.delegate = self
    self.treeTableView.dataSource = self

    let treeModel = TreeModel()
    treeModel.delegate = self
    treeModel.downloadItems()

}
    func itemsDownloaded(items: NSArray) {
    feedTrees = items
    self.treeTableView.reloadData()
}

После исправления проблемы вот так

    func itemsDownloaded(items: NSArray) {
    feedTrees = items
    self.treeTableView.reloadData()
}
override func viewDidLoad() {
    super.viewDidLoad()

    //table view delegats and datasource declaration
    self.treeTableView.delegate = self
    self.treeTableView.dataSource = self

    let treeModel = TreeModel()
    treeModel.delegate = self
    treeModel.downloadItems()

}

Просто переместите метод протокола в начало viewDidLoad ().

0 голосов
/ 02 октября 2018

URLSession dataTask является асинхронным, поэтому вы должны сделать обратный вызов, чтобы получить ваши данные.

Изменить код таким образом:

func downloadItems(completion: @escaping (_ result: Data?)->Void) {

let url: URL = URL(string: urlPath)!

let defaultSession = URLSession(configuration: URLSessionConfiguration.default)

let task = defaultSession.dataTask(with: url) {
    (data, response, error) in

    if error != nil {
        print("Failed to download data")
        completion(nil)
    }else {
        let httpResponse = response as? HTTPURLResponse
        print(httpResponse)
        // remove this
        //self.data = data!
        //print("Data downloaded")
        //self.parseJSON(self.data)

        //add this
         guard let data = data else{return}
         completion(data)
    }

}

    task.resume()
}

Затем вы можете вызывать свой метод в любом месте таким образом:

downloadItems{ data in
 self.data = self.parseJSON(data)

}

РЕДАКТИРОВАТЬ: Так что в вашем случае вы должны изменить это:

treeModel.downloadItems(completion: <#T##(Data?) -> Void#>)

в это:

treeModel.downloadItems{ data in
    feedTrees = self.parseJSON(data)
}

Я говорю это, потому что вы функция parseJSON ничего не возвращает, поэтому я предполагаю, что вы parseJSON неправильно

Я бы сделал это следующим образом:

ПРИМЕЧАНИЕ: эта функция предполагает, что ваш feedTrees - NSMutableArray

//Make your function return NSMutable array
func parseJSON(_ data: Data) -> NSMutableArray{
   var jsonResult = NSArray()
   //Put all of your code into do-catch
do{
    jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! NSArray

var jsonElement = NSDictionary()
let forest = NSMutableArray()

for tree in 0 ..< jsonResult.count {

    jsonElement = jsonResult[tree] as! NSDictionary

    let tempTree = trees()

    if let latinName = jsonElement["latin_name"] as? String,
    let turkishName = jsonElement["turkish_name"] as? String,
    let seedType = jsonElement["seed_type"] as? Int,
    let leafType = jsonElement["leaf_type"] as? Int,
    let spreadingArea = jsonElement["spreading_area"] as? String,
    let bothanicalProp = jsonElement["bothanical_prop"] as? String {
        tempTree.latin_name = latinName
        tempTree.turkish_name = turkishName
        tempTree.seed_type = seedType
        tempTree.leaf_type = leafType
        tempTree.spreading_area = spreadingArea
        tempTree.botanical_prop = bothanicalProp

        //Add here your tree or it can be empty
        forest.add(tempTree)
    }

}

 //AFTER THE LOOP
 return forest

} catch let error as NSError {
    print(error)
}

}
0 голосов
/ 03 октября 2018

Кажется, ваш API возвращает turkis_name вместо turkish_name:

"turkis_name" = "Maynum \U00c7\U0131kmaz A\U011fac\U0131";

Скажите, что инженеры на стороне сервера исправят его, чтобы следовать спецификации API.Или это вы неправильно прочитали спецификацию API?


В любом случае, когда вам нужно адаптировать код к фактическому ответу, вам может потребоваться исправить только одну строку.

    let turkishName = jsonElement["turkis_name"] as? String,

Но я даю вам практически полезный совет:

Не игнорируйте ошибки или неверные вводы молча.

С некоторыми изменениями, чтобы сделать ваш код более быстрым, ваш parseJSON(_:) будет примерно так:

func parseJSON(_ data: Data) -> NSArray {
    do{
        guard let jsonResult = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] else {
            print("Invalid JSON structure")
            return []
        }

        let forest = NSMutableArray()

        for jsonElement in jsonResult {
            if
                let latinName = jsonElement["latin_name"] as? String,
                let turkishName = jsonElement["turkis_name"] as? String, //###Use the right key here
                let seedType = jsonElement["seed_type"] as? Int,
                let leafType = jsonElement["leaf_type"] as? Int,
                let spreadingArea = jsonElement["spreading_area"] as? String,
                let bothanicalProp = jsonElement["bothanical_prop"] as? String
            {
                let tempTree = trees()

                tempTree.latin_name = latinName
                tempTree.turkish_name = turkishName
                tempTree.seed_type = seedType
                tempTree.leaf_type = leafType
                tempTree.spreading_area = spreadingArea
                tempTree.botanical_prop = bothanicalProp

                forest.add(tempTree)
            } else {
                //### Do not ignore errors or invalid inputs silently.
                print("Missing any of 'latin_name', 'turkis_name', 'seed_type', 'leaf_type', 'spreading_area', 'bothanical_prop'", jsonElement)
            }
        }
        return forest

    } catch let error {
        print(error)
        return []
    }
}

(Есть еще несколько частей, которые я хочу исправить, но для них нужно изменить скрытые части вашего кода, поэтому я сдался. И рассмотрим принятие Codable, при работе с JSON.)


Вам может потребоваться еще несколько исправлений, но когда вы пишете что-то о неожиданном результате, пожалуйста, не забудьте включить:

  • Конкретный выводфактический результат
  • В дополнение к тому, где и когда вы получите вывод
  • И ожидаемый результат

Установка оператора print и отображение вывода с кодомв том числе это был бы хороший способ.

0 голосов
/ 02 октября 2018

Если вы позвоните и потом ожидаете, что data будет не пустым, вы будете разочарованы.URLSession dataTask является асинхронным.Он не будет читать ваши данные, когда вернется функция downloadItems().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...