[решено] Функция возвращает пустой массив. Почему


#41

Запустите это:

func fetchData(completion: @escaping ([String]) -> Void) {
    var array = [String]()
    let group = DispatchGroup()
    for _ in 0..<3 {
        group.enter()
        let url = URL(string: "https://forum.swiftbook.ru/t/funkcziya-vozvrashhaet-pustoj-massiv-pochemu")!
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            enum Error: Swift.Error { case emptyData }
            do {
                guard let data = data else { throw error ?? Error.emptyData }
                array.append(String(data: data, encoding: .utf8)!)
            } catch let error {
                print("error", error)
            }
            group.leave()
        }.resume()
    }
    group.notify(queue: .main) {
        completion(array)
    }
}


fetchData { strings in
    print(strings)
}

Падает?


#42

если прям скопировать и вставить, то не падает. Но так и функция эта нифига не делает. Ей нечего добавлять в архив. strings в итоге нет


#43

вот моя исправленная функция

func fetchData(completion: @escaping ([String]) -> Void) {
    loadingActivityIndicator.startAnimating()
    bookmarksTable.isHidden = true
    var arrayOfBookmarks = [String]()
    let group = DispatchGroup()
    for i in 0..<arrayID.count {
        group.enter()
        let jsonURL = "https://mfc.group/mobile-api/get-news.php?linkCode=\(arrayLink[i])&elementId=\(arrayID[i])"
        guard let url = URL(string: jsonURL) else { return }
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            
            enum Error: Swift.Error { case emptyData }
            do {
                guard let data = data else { throw error ?? Error.emptyData }
                //let bookmarksMod = try JSONDecoder().decode(BookmarksModel.self, from: data)
                arrayOfBookmarks.append(String(data: data, encoding: .utf8)!)
                print(arrayOfBookmarks, "print 1")
                group.leave()
            } catch let error {
                print("json serialization error", error)
            }
            print(arrayOfBookmarks, "inside 2", arrayOfBookmarks.count)
            group.leave()
            }.resume()
        
        print(arrayOfBookmarks, "inside 3", arrayOfBookmarks.count)
    }
    group.notify(queue: .main) {
        completion(arrayOfBookmarks)
    }
    print(arrayOfBookmarks, "print 4")
}

попробуйте с переменной
arrayLink = [“news-trand”, “news-trand”]
arrayID = [“2730”, “2731”]


#44

хочется сгореть от стыда. Похоже я нашел свою ошибку


#45

@haymob я прошу прощения. я дважды написал group.leave(). Вот на втором leave() приложение и крашилось. Извиняюсь за столько отнятого времени. Большое спасибо. Данные при вызове функции приходят.


#46

Теперь подскажите, как избавиться от этого синтаксиса:

\"backgroundUrl\":\"https:\\/\\/mfc.group\\/upload\\/iblock\\/dba\\/pozitiv_prishel.jpg\",\"dateTime\":\"05.06.2019 13:09:50\",\"showCounter\":\"18\",\"author\":\"2630\",\"detailPageUrl\":\"https:\\/\\/mfc.group\\/analitika\\/trend\\/pozitiv-prishel-otkuda-ne-zhdali\\/\"}\n\n

Мне нужны данные в формате массива словарей, разобранного по модели. Но вот мне не понятно теперь что это? Как это декодировать?


#47

И еще один важный вопрос: ну грех после такого не начать изучать потоки. Посоветуйте литературу или курс по этой теме.


#48

все, с этим разобрался


#49

#50

Спасибо за ссылку, начну изучать.
Всем большое спасибо за участие. Все работает как часы.


#51

А ведь можно было сделать все проще и без потоков.


#52

Ну ждем же с нетерпением…


#53

Можно, с промисами например:

Я бы именно так и сделал :slight_smile:


#54

Преподаватель из вас не очень бы получился :slight_smile:
Вы пытаетесь научить сразу прыгать, вместо того, что бы научить сперва ходить.
Но я не спорю что такие решения намного элегантнее и по феншую.
Но для новичков куда проще был бы самый простой вариант.
Тут достаточно было бы сделать счетчик запросов и проверку счетчика по выполнению каждого запроса.
Укороченный вариант

func fetchData() {
    let requestCount = arrayID.count
    var count = 0
    for i in 0..<arrayID.count {
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            count += 1
            // get data, append to array
            if count == arrayID.count - 1 {
                self.doSomething()
            }
        }.resume()
    }
}

func doSomething() {}

#55

Я сначала что-то подобное и пытался реализовать. Только проверку счетчика не делал.


#56

DispatchGroup это самый минимум, думаете его просто так придумали?


#57

Всегда можно обойтись базовыми знаниями и навыками.
Это ведь самое первое чему учат в вузах. Тут главное правильно сформировать алгоритм работы. По крайней мере нас так учили на 1м курсе. Да и препод был шикарный.

Я показал пример без DispatchGroup, значит это не самый минимум.


#58

Вы показали не потокобезопасную переменную. Это не минимум, это антипаттерн(((


#59

Не спорьте с дураком, не переспорите!


#60

Спорить похоже бессмысленно :slight_smile: Попробуйте такой тест (каждый раз результат может быть разный):

func test() {
    let count = 1000
    var array = [Int]()
    for _ in 0..<100 {
        var current = 0
        for _ in 0..<count {
            DispatchQueue.global().async {
                current += 1
                if current == count - 1 {
                    array.append(0)
                    print(array.count)
                }
            }
        }
    }
}

Сколько раз из 100, у вас срабатывает условие “current == count - 1”?