1

我的应用程序中有一个烦人的错误,每次加载UICollectionView控制器时,它都会复制单元格。

所以这是第一次加载集合视图的时间:

在此处输入图像描述

我有 2 个视图控制器,所以这是第二个视图控制器。如果我回到第一个视图控制器,它只有一个按钮到第二个视图控制器,然后再次转到触发 reloadData 函数的第二个视图控制器,就会发生这种情况:

在此处输入图像描述

我不太确定为什么会这样,我正在使用 Todd Kramer 的UICollectionView缓存图像:http ://www.tekramer.com/downloading-images-asynchronously-in-swift-with-alamofire/唯一的区别是我'm 从 JSON 异步加载图像 url 和数据,而不是像教程那样在模型或 plist 中静态定义。

以下是我在代码中所做的更改的类:

import UIKit
import SwiftyJSON

private let PhotoCollectionViewCellIdentifier = "cell"

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

@IBOutlet weak var collectionView: UICollectionView!

var index: NSIndexPath!

var names = [String]()
var imgsUrl = [String]()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let photo = PhotosDataManager()
    let api = Api()

    api.loadJsonData(self.names, imgsUrl: self.imgsUrl, batch: "2016", dept: "dafa") { names, imgsUrl in
        self.names = names
        self.imgsUrl = imgsUrl
        photo.allPhotos(self.names, imgUrls: self.imgsUrl)
        self.collectionView.reloadData()
    }
}

@IBAction func button(sender: UIButton) {
    NSNotificationCenter.defaultCenter().postNotificationName("alert1", object: self, userInfo: nil)
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    return PhotosDataManager.sharedManager.allPhotos(self.names, imgUrls: self.imgsUrl).count
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(PhotoCollectionViewCellIdentifier, forIndexPath: indexPath) as! CollectionViewCell
    dispatch_async(dispatch_get_main_queue(), {
        cell.configure(self.glacierScenicAtIndex(indexPath))
    })

    return cell
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    PhotosDataManager.sharedManager.purgeCache()
    self.performSegueWithIdentifier("previousViewController", sender: self)

}

func glacierScenicAtIndex(indexPath: NSIndexPath) -> GlacierScenic {
    let photos = PhotosDataManager.sharedManager.allPhotos(self.names, imgUrls: self.imgsUrl)
    return photos[indexPath.row]
}

}

class PhotosDataManager {

static let sharedManager = PhotosDataManager()
private var photos = [GlacierScenic]()

let decoder = ImageDecoder()
let photoCache = AutoPurgingImageCache(
    memoryCapacity: 100 * 1024 * 1024,
    preferredMemoryUsageAfterPurge: 60 * 1024 * 1024
)

func allPhotos(names: [String], imgUrls: [String]) -> [GlacierScenic] {

    var glacierScenic: GlacierScenic!

    for i in 0 ..< names.count {
        glacierScenic = GlacierScenic(name: names[i], photoURLString: imgUrls[i])
        photos.append(glacierScenic)
    }

    return photos
}

func getNetworkImage(urlString: String, completion: (UIImage -> Void)) -> (ImageRequest) {
    let queue = decoder.queue.underlyingQueue
    let request = Alamofire.request(.GET, urlString)
    let imageRequest = ImageRequest(request: request)
    imageRequest.request.response(
        queue: queue,
        responseSerializer: Request.imageResponseSerializer(),
        completionHandler: { response in
            guard let image = response.result.value else {
                return
            }
            let decodeOperation = self.decodeImage(image) { image in
                completion(image)
                self.cacheImage(image, urlString: urlString)
            }
            imageRequest.decodeOperation = decodeOperation
        }
    )
    return imageRequest
}

func decodeImage(image: UIImage, completion: (UIImage -> Void)) -> DecodeOperation {
    let decodeOperation = DecodeOperation(image: image, decoder: self.decoder, completion: completion)
    self.decoder.queue.addOperation(decodeOperation)
    return decodeOperation
}

func cacheImage(image: Image, urlString: String) {
    photoCache.addImage(image, withIdentifier: urlString)
}

func cachedImage(urlString: String) -> Image? {
    return photoCache.imageWithIdentifier(urlString)
}

func purgeCache() {
//        photoCache.removeAllImages()
    print("memory used: \(photoCache.memoryUsage)")
}

}

class PhotosDataManager {

static let sharedManager = PhotosDataManager()
private var photos = [GlacierScenic]()

let decoder = ImageDecoder()
let photoCache = AutoPurgingImageCache(
    memoryCapacity: 100 * 1024 * 1024,
    preferredMemoryUsageAfterPurge: 60 * 1024 * 1024
)

func allPhotos(names: [String], imgUrls: [String]) -> [GlacierScenic] {

    var glacierScenic: GlacierScenic!

    for i in 0 ..< names.count {
        glacierScenic = GlacierScenic(name: names[i], photoURLString: imgUrls[i])
        photos.append(glacierScenic)
    }

    return photos
}

func getNetworkImage(urlString: String, completion: (UIImage -> Void)) -> (ImageRequest) {
    let queue = decoder.queue.underlyingQueue
    let request = Alamofire.request(.GET, urlString)
    let imageRequest = ImageRequest(request: request)
    imageRequest.request.response(
        queue: queue,
        responseSerializer: Request.imageResponseSerializer(),
        completionHandler: { response in
            guard let image = response.result.value else {
                return
            }
            let decodeOperation = self.decodeImage(image) { image in
                completion(image)
                self.cacheImage(image, urlString: urlString)
            }
            imageRequest.decodeOperation = decodeOperation
        }
    )
    return imageRequest
}

func decodeImage(image: UIImage, completion: (UIImage -> Void)) -> DecodeOperation {
    let decodeOperation = DecodeOperation(image: image, decoder: self.decoder, completion: completion)
    self.decoder.queue.addOperation(decodeOperation)
    return decodeOperation
}

func cacheImage(image: Image, urlString: String) {
    photoCache.addImage(image, withIdentifier: urlString)
}

func cachedImage(urlString: String) -> Image? {
    return photoCache.imageWithIdentifier(urlString)
}

func purgeCache() {
//        photoCache.removeAllImages()
    print("memory used: \(photoCache.memoryUsage)")
}

}
4

1 回答 1

2

问题

在 PhotosDataManager => 您正在使用 sharedManager 引用,它将对象引用保存在静态引用中并继续重用它,在所有 segues 导航中,因此您的 allPhotos 方法,继续在旧数组中添加数据。

 static let sharedManager = PhotosDataManager()

另一个问题

不要在 numberOfItemsInSection 中调用 allPhotos 方法,因为它会被多次调用,这可能会多次附加数据


解决方案

在你的方法中:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

     //USE Instantiated reference
    return photos.getPhotosCount()
}

相反,在你的类 PhotosDataManager

class PhotosDataManager {

  func getPhotosCount(){

    return photos.count
  }
}
于 2016-06-24T05:11:24.313 回答