异步获取数据并将其放入UICollectionView失败-集合在数据之前加载,不会更新



我的问题部分与我在这里的另一个问题有关当用户滚动我的应用程序中的UIViewCollectionCells列表时的奇怪行为(每个单元格中的数据随机变化)

在我的应用程序中,我使用UICollectionView。每个单元格都包含一张照片和一个用户名。

但首先,我要从我的Web服务中获取一个json文件,其中包含该用户名和一个照片链接。我将这两个值都存储在一个名为SingleUser的对象中。它看起来像这样:

class SingleUser: NSObject {
let username: String
let photo: String
var image: UIImage? = UIImage()
init(username: String, photo: String) {
    self.username = username
    self.photo = photo
}
class func fromJSON(json: JSON) -> SingleUser? {
    let username = json["username"].string
    let photo = json["photo"].string
    return SingleUser(username: username!, photo: photo!)
}
}

根据上一个问题的建议,我修改了代码,使用UICollectionView的主类如下所示:

class UserList: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet weak var tview: UICollectionView!
let reuseIdentifier = "cell" 
var items = NSMutableArray()
override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    fetchAllUsers()
    tview.delegate = self
    tview.dataSource = self
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = tview.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
    let user:SingleUser =  self.items[indexPath.item] as! SingleUser   
    cell.username.text = user.name
    if user.image == nil{
        if let checkedUrl = NSURL(string: user.photo) {
            cell.userImg.contentMode = .ScaleAspectFit
            getDataFromUrl(checkedUrl) { (data, response, error)  in
                dispatch_async(dispatch_get_main_queue()) { () -> Void in
                    guard let data = data where error == nil else { return }
                    let image  = UIImage(data: data)
                    user.image = image
                    if collectionView.cellForItemAtIndexPath(indexPath) == cell
                    {
                        cell.userImg.image = image
                    }
                }
            }
        }else{
            cell.userImg.image = user.image
        }
    return cell
}

所以现在,希望每次用户滚动视图时,数据不会发生变化。但这里有一个主要问题——当用户进入面板时,collectionView会显示出来,但所有照片都无法快速加载。所以用户只能看到用户名,照片的位置是空的。

原因是我使用viewWillAppear:中调用的方法fetchAllUsers异步加载数据

func fetchAllUsers(){
    Alamofire.request(.GET, "http://mywebservice")
        .responseJSON { response in
            switch response.result {
            case .Success:
                dispatch_async(dispatch_get_main_queue(),{
                    self.items.removeAllObjects()
                    if let jsonData = response.result.value as? [[String: AnyObject]] {
                        for requestJSON in jsonData {
                            if let request = SingleUser.fromJSON(JSON(requestJSON)){
                                self.items.addObject(request)
                                self.tview.reloadData()

                            }
                        }
                    }
                    self.tview.reloadData()
                })
            case .Failure(let error):
                print("SWITCH ERROR")
                print(error)
            }
    }
}

另外,我在上面使用的另一个异步方法是:

func getDataFromUrl(url:NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
    NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
        completion(data: data, response: response, error: error)
        }.resume()
}

因此,这里有很多异步调用会导致在视图出现之前显示数据不足的问题。

我想避免这种情况,相反——例如,当每张照片还没有加载时——显示例如,当照片被提取时,加载指示器会消失。我知道可能有必要对我的代码进行大量修改,但我可以在这里向你寻求任何建议吗?谢谢

实际上,每当下载新数据时,都需要重新加载收集数据。

最好的方法可能是关闭"getDataFromURL",在此关闭中执行以下操作:

dispatch_async(dispatch_get_main_queue()) {
  tview.reloadData()
}

要获得加载图像,只需将所需的图像放在用户图像后面的原型单元中即可。这将是可见的,直到用户的图像显示出来。

相关内容

  • 没有找到相关文章

最新更新