从Web检索新数据后,无法使用自定义布局更新UICollectionView

时间:2016-06-15 19:12:50

标签: ios swift2 uicollectionview alamofire

在我的应用程序中有一个集合视图,当我到达最后一个项目时必须更新(在底部加载新帖子)。 我正在使用Alamofire获取新帖子。 此外,我的集合视图具有自定义布局。 奇怪的是:当应用程序第一次加载时,集合视图正确更新,我可以看到帖子的第一部分,但是当我滚动并调用方法来加载更多时,它会加载帖子,将其附加到数据源,但是集合视图即使我尝试在主队列上更新它,也无法获得更新。

我的代码:

FeedViewController.swift:

private let reuseIdentifier = "Cell"

class FeedViewController: UICollectionViewController {

var posts : [GPost] = []
var offsetForPosts = 0
let limitForPosts = 50

override func viewDidLoad() {
        super.viewDidLoad()

        if let layout = collectionView?.collectionViewLayout as? FeedLayout {
            layout.delegate = self
        }

        self.collectionView?.registerNib(UINib(nibName: "GCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifier)

        let initialPath : URLStringConvertible = "\(DEFAULT_PATH)api_key=\(API_KEY)&offset=\(offsetForPosts)&limit=\(self.limitForPosts)"

        self.loadPostsForPath(initialPath) { (_posts) in
            self.posts.appendContentsOf(_posts)
            print(self.posts.count)
            dispatch_async(dispatch_get_main_queue(), {
                self.collectionView?.reloadData()
            })
        }

    }

func loadPostsForPath(path: URLStringConvertible, completion: (posts: [GPost]) -> ()) {

            Alamofire.request(.GET, path, parameters: nil, encoding: .JSON, headers: nil).responseJSON { (response) in

                switch response.result {
                case .Success(let data):

                    let JSONData = JSON(data)
                    var result = [GPost]()

                    for (_, value) in JSONData["data"] {
                        let post = GPost(id: value["id"].stringValue,
                            url: NSURL(string: value["images"]["fixed_width_downsampled"]["url"].stringValue)!,
                            slug: value["slug"].stringValue,
                            imageWidth: CGFloat(value["images"]["original"]["width"].floatValue),
                            imageHeight: CGFloat(value["images"]["original"]["height"].floatValue))

                        result.append(post)
                    }

                    completion(posts: result)

                    break
                case .Failure(let error):
                    print("Error loading posts: \(error)")
                    break
                }

            }

        }


override func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {

            if indexPath.item == posts.count - 10 {

                dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
                        self.offsetForPosts += 50
                        let path : URLStringConvertible = "\(DEFAULT_PATH)api_key=\(API_KEY)&offset=\(self.offsetForPosts)&limit=\(self.limitForPosts)"
                        self.loadPostsForPath(path, completion: { (_posts) in
                            self.posts.appendContentsOf(_posts)
                            print(self.posts.count)
                            dispatch_async(dispatch_get_main_queue(), {
                                self.collectionView?.reloadData()
                                self.collectionView?.collectionViewLayout.invalidateLayout()
                            })
                        })
                })

            }

            }
}

extension FeedViewController : FeedLayoutDelegate {

    func collectionView(collectionView: UICollectionView, heightForPostAtIndexPath indexPath: NSIndexPath, withWidth width: CGFloat) -> CGFloat {

        let post = posts[indexPath.item]

        return width * post.getProportion() + 30

    }

}

FeedLayout.swift:

protocol FeedLayoutDelegate {
    func collectionView(collectionView: UICollectionView, heightForPostAtIndexPath indexPath: NSIndexPath, withWidth width: CGFloat) -> CGFloat
}

class FeedLayout: UICollectionViewLayout {


    var delegate : FeedLayoutDelegate!

    var numberOfColumns = 2
    var cellPadding : CGFloat = 0.0

    private var cache = [UICollectionViewLayoutAttributes]()

    private var contentHeight : CGFloat = 0.0
    private var contentWidth : CGFloat {
        let insets = collectionView!.contentInset
        return CGRectGetWidth(collectionView!.bounds) - (insets.left + insets.right)
    }


    override func prepareLayout() {

        if cache.isEmpty {

            let columnWidth = contentWidth / CGFloat(numberOfColumns)
            var xOffset = [CGFloat]()
            for column in 0..<numberOfColumns {
                xOffset.append(CGFloat(column) * columnWidth)
            }
            var column = 0
            var yOffset = [CGFloat](count: numberOfColumns, repeatedValue: 0)

            for item in 0..<collectionView!.numberOfItemsInSection(0) {
                let indexPath = NSIndexPath(forItem: item, inSection: 0)

                let width = columnWidth - cellPadding * 2
                let height = cellPadding + delegate.collectionView(collectionView!, heightForPostAtIndexPath: indexPath, withWidth: width) + cellPadding
                let frame = CGRectMake(xOffset[column], yOffset[column], columnWidth, height)
                let insetFrame = CGRectInset(frame, cellPadding, cellPadding)

                let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
                attributes.frame = insetFrame
                cache.append(attributes)

                contentHeight = max(contentHeight, CGRectGetMaxY(frame))
                yOffset[column] = yOffset[column] + height

                column = column >= (numberOfColumns - 1) ? 0 : column + 1

            }

        }

    }

    override func collectionViewContentSize() -> CGSize {
        return CGSizeMake(contentWidth, contentHeight)
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

        var layoutAttributes = [UICollectionViewLayoutAttributes]()

        for attributes in cache {
            if CGRectIntersectsRect(attributes.frame, rect) {
                layoutAttributes.append(attributes)
            }
        }

        return layoutAttributes
    }



}

0 个答案:

没有答案