Ich habe diesen nervigen Fehler in meiner App, dass jedes Mal, wenn ich den UICollectionView
-Controller lade, er die Zellen dupliziert.Swift 2 reloadData fügt dem UICollectionView weitere Zellen hinzu
Das ist also die, wenn die Sammlung Ansicht lädt zum ersten Mal:
Ich habe 2 View-Controller so ist dies der zweite View-Controller ist. Wenn ich an den ersten View-Controller abschalten zurück, die nur 1 Taste zum 2. View-Controller hat und segue wieder in den zweiten View-Controller, der die reload Funktion auslöst, geschieht dies:
Ich bin nicht wirklich sicher, warum das passiert, ich verwende Todd Kramer's UICollectionView
mit zwischengespeicherten Bildern: http://www.tekramer.com/downloading-images-asynchronously-in-swift-with-alamofire/ Der einzige Unterschied ist, dass ich die Bild URLs und Daten von JSON asynchron laden, anstatt statisch in einem Modell oder Plist wie das Tutorial zu definieren.
Hier sind die Klassen mit Änderungen, die ich im Code gemacht:
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)")
}
}
in den allphotos Funktion, die Sie for-Schleife verwenden, die gleichen Daten immer wieder anhängen. –