swift - 如果执行嵌套异步调用,则函数运行两次,否则运行一次。需要帮助预先确定这种情况何时发生

标签 swift

func handleGetAllPhotoURLs 从下面的行调用,我已确认该代码行仅在断点处执行一次。

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

根据我的 print 语句的输出,该函数运行两次,因为如果 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 为空时显示它。

现在,如果 urls 不为空,应用程序会很快闪烁空消息 UILabel。现在这对我来说是有意义的,因为 print 语句显示 urls 数组暂时为空。

有没有办法让我确定当 urls.count 非零时避免向用户闪烁空消息 UILabel?

编辑:根据请求添加了下面的代码。调用以下函数以在完成处理程序中获取 [URL]。然后完成处理程序被输入: func handleGetAllPhotoURLs(pin: Pin, urls: [URL], error: 错误?)

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
}

最佳答案

do block 中,您调用了 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
}

关于swift - 如果执行嵌套异步调用,则函数运行两次,否则运行一次。需要帮助预先确定这种情况何时发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55625101/

相关文章:

swift - 填充核心数据多对多关系

ios - 在 TableView 索引列表中显示整个字母表(横向)

swift - 为什么清除 Realm 表的内容会使对象失效?

ios - 试图在全局范围内访问响应

ios - 滚动 uitableviewcell 后 UIView.animateWithDuration 停止

ios - UICollectionView 没有通过 cellForItemAt 正确更新所有单元格

ios - GPUImageUIElement 叠加大小

swift - 协议(protocol)对保留计数有影响吗?

swift - 获取分段上传 Alamofire5 的上传进度

ios - SwiftUI:什么是@AppStorage 属性包装器