Функция запускается дважды, если выполняются вложенные асинхронные вызовы, и один раз в противном случае. Нужна помощь, предварительно определив, когда это произойдет - PullRequest
2 голосов
/ 11 апреля 2019

func handleGetAllPhotoURLs вызывается из строки ниже, и я подтвердил, что строка кода выполняется только один раз с точками останова.

_ = FlickrClient.getAllPhotoURLs(currentPin: self.currentPin, fetchCount: fetchCount, completion: self.handleGetAllPhotoURLs(pin:urls:error:))

Согласно выводу из моих операторов печати,Функция запускается дважды, потому что она печатает две строки вывода, если urls.count не равен нулю.Однако, если urls.count равен нулю, я получаю только один оператор печати, в котором говорится: «urls.count ---> 0»

handleGetAllPhotoURLs ---> urls.count ---> 0 // эта строка всегда печатается

handleGetAllPhotoURLs ---> urls.count ---> 21 // эта строка печатается, только если параметр urls не пуст

func handleGetAllPhotoURLs(pin: Pin, urls: [URL], error: Error?){
    print("handleGetAllPhotoURLs ---> urls.count  ---> \(urls.count)")

    let backgroundContext: NSManagedObjectContext! = dataController.backGroundContext
    if let error = error {
        print("func mapView(_ mapView: MKMapView, didSelect... \n\(error)")
        return
    }

    let pinId = pin.objectID
    backgroundContext.perform {
        let backgroundPin = backgroundContext.object(with: pinId) as! Pin
        backgroundPin.urlCount = Int32(urls.count)
        try? backgroundContext.save()
    }

    for (index, currentURL) in urls.enumerated() {
        URLSession.shared.dataTask(with: currentURL, completionHandler: { (imageData, response, error) in
            guard let imageData = imageData else {return}
            connectPhotoAndPin(dataController: self.dataController, currentPin:  pin , data: imageData, urlString: currentURL.absoluteString, index: index)
        }).resume()
    }
}

Кроме того, у меня есть UILabel, которая открывается только тогда, когда urls.count равен нулю, и я хочу показывать ее только тогда, когда urls пуст.

Прямо сейчас, если URL не пуст, приложение очень быстро мигает пустым сообщением UILabel.Что сейчас имеет для меня смысл, потому что оператор print показывает, что массив urls временно пуст.

Есть ли способ для меня, чтобы определить, не показывать ли пользователю пустое сообщение UILabel, когда urls.count не равен нулю?

edit: добавлен код ниже по запросу.Функция ниже вызывается для получения [URL] в обработчике завершения.Затем обработчик завершения подается в: func handleGetAllPhotoURLs (pin: Pin, urls: [URL], ошибка: ошибка?)

class func getAllPhotoURLs(currentPin: Pin, fetchCount count: Int, completion: @escaping (Pin, [URL], Error?)->Void)-> URLSessionTask?{
    let latitude = currentPin.latitude
    let longitude = currentPin.longitude
    let pageNumber = currentPin.pageNumber


    let url = Endpoints.photosSearch(latitude, longitude, count, pageNumber).url

    var array_photo_URLs = [URL]()
    var array_photoID_secret = [[String: String]]()
    var array_URLString = [String]()
    var array_URLString2 = [String]()
    var count = 0

    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        guard let dataObject = data, error == nil else {
            DispatchQueue.main.async {
                completion(currentPin, [], error)
            }
            return
        }

        do {
            let temp = try JSONDecoder().decode(PhotosSearch.self, from: dataObject)
            temp.photos.photo.forEach{
                let tempDict = [$0.id : $0.secret]
                array_photoID_secret.append(tempDict)

                let photoURL = FlickrClient.Endpoints.getOnePicture($0.id, $0.secret)
                let photoURLString = photoURL.toString
                array_URLString.append(photoURLString)

                getPhotoURL(photoID: $0.id, secret: $0.secret, completion: { (urlString, error) in
                    guard let urlString = urlString else {return}
                    array_URLString2.append(urlString)
                    array_photo_URLs.append(URL(string: urlString)!)
                    count = count + 1
                    if count == temp.photos.photo.count {
                        completion(currentPin, array_photo_URLs, nil)
                    }
                })
            }
            completion(currentPin, [], nil)
            return
        } catch let conversionErr {
            DispatchQueue.main.async {
                completion(currentPin, [], conversionErr)
            }
            return
        }
    }
    task.resume()
    return task
}

1 Ответ

2 голосов
/ 11 апреля 2019

В блоке do вы звоните completion дважды.Пожалуйста, смотрите исправление,

do {
    let temp = try JSONDecoder().decode(PhotosSearch.self, from: dataObject)
    if temp.photos.photo.isEmpty == false {
       temp.photos.photo.forEach{
        let tempDict = [$0.id : $0.secret]
        array_photoID_secret.append(tempDict)

        let photoURL = FlickrClient.Endpoints.getOnePicture($0.id, $0.secret)
        let photoURLString = photoURL.toString
        array_URLString.append(photoURLString)

        getPhotoURL(photoID: $0.id, secret: $0.secret, completion: { (urlString, error) in
            guard let urlString = urlString else {return}
            array_URLString2.append(urlString)
            array_photo_URLs.append(URL(string: urlString)!)
            count = count + 1
            if count == temp.photos.photo.count {
                completion(currentPin, array_photo_URLs, nil)
            }
        })
      }
    } else {
        completion(currentPin, [], nil)
    }
    return
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...