等待后台请求在Alamofire完成并且数组加载之前继续迅速

我知道这里还有另外一个问题,但这个问题没有被任何人清楚的回答,也没有被接受的答案。 我有一个方法loadDetail需要一个completionHandler使用UIBackgroundFetchResult。 当我select一个单元格从数组中加载该单元格的详细数据时,将调用此方法。 当这个方法被调用时,我想要调用的方法等待,直到detailResults数组被填充,然后再继续。 我怎么能做到这一点,我做错了什么?

func loadDetail(urlPath: String, completionHandler: ((UIBackgroundFetchResult) -> Void)!){ Alamofire.request(.GET, urlPath) .responseJSON { _, _, result in switch result { case .Success(let data): let jsonObj = JSON(data) if let data = jsonObj["results"].arrayValue as [JSON]? { //array is filled in the line below self.detailResults = data self.collectionView.reloadData() } case .Failure(_, let error): print("Request failed with error: \(error)") } } completionHandler(UIBackgroundFetchResult.NewData) print("Background Fetch Complete") } 

这里是loadDetail被调用的collectionView方法,你可以看到它被调用的注释,与我想要做的事情有关。

 func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { let data = results?[indexPath.row] let detailData: JSON var testString: String = "" let vc: DetailBrowseViewController = self.storyboard?.instantiateViewControllerWithIdentifier("DetailBrowseViewController") as! DetailBrowseViewController if let titleString = data?["title"] { vc.titleString = titleString.stringValue testString = titleString.stringValue testString = testString.stringByReplacingOccurrencesOfString(" ", withString: "-") testString = testString.lowercaseString reusableUrl.replaceRange(Range<String.Index>(start: reusableUrl.startIndex.advancedBy(146), end: reusableUrl.startIndex.advancedBy(146)), with: testString) self.loadDetail(reusableUrl, completionHandler:{(UIBackgroundFetchResult) -> Void in //I want this collectionView method to somehow pause and wait until the detailResults array is filled and then continue print("success") }) } detailData = (detailResults?[indexPath.row])! if let priceString = detailResults?[indexPath.row]["price"] { print(detailData) vc.priceString = priceString.stringValue } self.navigationController?.pushViewController(vc, animated: true) } 

问题是,loadDetail方法直接通过,而无需等待,导致数组在其调用collectionView方法时为零。

据我所知,当self.detailResults填充响应中的JSON数据时,您需要调用completionHandler

我将尝试去理解我们的主要想法: – 只有当数据被成功parsing时才会调用competitionHandler – 将必要的代码(应该等待响应)移动到已经加载数据的地方。

首先,您需要将completionHandler调用移动到.Success大小写块的末尾。 如果回应失败,我认为你不需要前进。

所以结果是:

 func loadDetail(urlPath: String, completionHandler: ((UIBackgroundFetchResult) -> Void)!){ Alamofire.request(.GET, urlPath) .responseJSON { _, _, result in switch result { case .Success(let data): let jsonObj = JSON(data) if let data = jsonObj["results"].arrayValue as [JSON]? { //array is filled in the line below self.detailResults = data self.collectionView.reloadData() completionHandler(UIBackgroundFetchResult.NewData) } case .Failure(_, let error): print("Request failed with error: \(error)") } } print("Background Fetch Complete") } 

然后你需要将相关的代码(应该等待响应)移动到completionHandler如下所示:

 func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { let data = results?[indexPath.row] let detailData: JSON var testString: String = "" let vc: DetailBrowseViewController = self.storyboard?.instantiateViewControllerWithIdentifier("DetailBrowseViewController") as! DetailBrowseViewController if let titleString = data?["title"] { vc.titleString = titleString.stringValue testString = titleString.stringValue testString = testString.stringByReplacingOccurrencesOfString(" ", withString: "-") testString = testString.lowercaseString reusableUrl.replaceRange(Range<String.Index>(start: reusableUrl.startIndex.advancedBy(146), end: reusableUrl.startIndex.advancedBy(146)), with: testString) self.loadDetail(reusableUrl, completionHandler:{(UIBackgroundFetchResult) -> Void in //I want this collectionView method to somehow pause and wait until the detailResults array is filled and then continue print("success") detailData = (detailResults?[indexPath.row])! if let priceString = detailResults?[indexPath.row]["price"] { print(detailData) vc.priceString = priceString.stringValue } self.navigationController?.pushViewController(vc, animated: true) }) } }