如果执行嵌套的异步调用,则函数运行两次,否则运行一次。需要帮助来预先确定何时会发生这种情况
Posted
技术标签:
【中文标题】如果执行嵌套的异步调用,则函数运行两次,否则运行一次。需要帮助来预先确定何时会发生这种情况【英文标题】:Function runs twice if nested async calls are executed and once otherwise. Need help pre-determining when this will happen 【发布时间】:2019-04-11 05:07:48 【问题描述】: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 为空时显示它。
现在,如果 urls 不为空,应用程序会非常快速地闪烁空消息 UILabel。现在这对我来说很有意义,因为 print 语句显示 urls 数组暂时为空。
当 urls.count 不为零时,我有没有办法确定避免向用户闪烁空消息 UILabel?
编辑:根据要求在下面添加了代码。调用下面的函数以在完成处理程序中获取 [URL]。然后完成处理程序被送入: func handleGetAllPhotoURLs(pin: Pin, urls: [URL], error: 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
【问题讨论】:
函数的内容不影响函数被调用的次数。我们必须看看你是如何调用那个方法的。 嗨。进行了编辑,希望能提供更多信息。 class func getAllPhotoURLs() 返回一个完成处理程序,然后进入 func handleGetAllPhotoURLs()。如果还有什么我可以提供的帮助,请告诉我 【参考方案1】:在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
【讨论】:
非常感谢。我找错地方了。没有意识到我两次返回完成处理程序。以上是关于如果执行嵌套的异步调用,则函数运行两次,否则运行一次。需要帮助来预先确定何时会发生这种情况的主要内容,如果未能解决你的问题,请参考以下文章