滚动

时间:2017-02-04 17:26:00

标签: ios swift uicollectionview uicollectionviewcell

我遇到UICollectionView中的单元格问题,当向上或向下滚动时图像混合在一起。它会混淆然后保持混合状态,否则它会恢复正常的顺序。

class booksVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
    var imageIdsonDB : [String] = []
    var imageIds : [String] = []

    @IBOutlet weak var collectionView: UICollectionView!

    var posts = [Post]()
    let db : DBHelper = DBHelper()
    var arrayBooks = [BookModel]()
    var selectedIndexPath : IndexPath = IndexPath()
    var post: Post!

    override func viewDidLayoutSubviews() {
        adjustViewLayout(size: UIScreen.main.bounds.size)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.delegate = self
        collectionView.dataSource = self
        for item in self.db.fetchAll() {
            imageIdsonDB.append(item.id)
        }

        self.arrayBooks.removeAll()
        self.arrayBooks.append(contentsOf: self.db.fetchAll())
        self.collectionView.reloadData()

        DataService.ds.REF_POSTS8.observe(.value, with: { (snapshot) in

            if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
                for snap in snapshot {
                    print ("SNAP: \(snap)")
                    if let postDict = snap.value as? Dictionary<String, AnyObject>{
                        let key = snap.key
                        let post = Post(postKey: key , postData: postDict)
                        self.posts.append(post)
                        self.db.insertBook(id: postDict["id"] as! String, imgName: postDict["id"] as! String, imgPath: "", bookName: postDict["book_name"] as! String, bookPath: "", imageURL: postDict["image_path"] as! String, bookURL: postDict["book_path"] as! String, caption: "")
                    }
                }
            }
            self.arrayBooks.removeAll()
            self.arrayBooks.append(contentsOf: self.db.fetchAll())
            self.collectionView.reloadData()
        })
        // update db for changed database data
        for image in self.db.fetchAll() {
            if !self.imageIds.contains(image.id) {
                self.db.deleteBook(id: image.id)
            }
        }
        self.collectionView.reloadData()
    }
    func getFilePath(name : String) -> String {
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let filePath = documentsPath+"/"+name
        return filePath
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return arrayBooks.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let book = arrayBooks[indexPath.item]
        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)as? collectionViewCellBooks {
            SwiftLoader.hide()
            cell.initWithBook(book: book)
            return cell
        } else {
            return collectionViewCellBooks()  
        } 
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.selectedIndexPath = indexPath
        self.performSegue(withIdentifier: "showImage", sender: self)
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    { 
        if segue.identifier == "showImage"
        {
            let vc = segue.destination as! showPdfVC
            vc.book = self.arrayBooks[self.selectedIndexPath.row]
        }
    } 
}

initwithBook功能的代码是

func initWithBook(book : BookModel) {
    self.caption.text = book.bookName
    if book.thumbImagePaht == "" {
        let ref = FIRStorage.storage().reference(forURL: book.imageURL)
       let downloadTask =  ref.data(withMaxSize: 4 * 1024 * 1024, completion: { (data,error) in
            if error != nil {    
            }else {
                if let imgData = data {
                    if let img = UIImage(data: imgData) {
                        self.imageView.image = img
                        let imageName = book.id+".jpg"
                        let filepath = self.getFilePath(name: imageName)
                        if (try? data?.write(to: URL(fileURLWithPath: filepath),options: [.atomic])) != nil {
                            self.db.upDateImagePath(id: book.id, imagePath: filepath)
                        }
                        self.stopLoading();
                    }
                }
            }
        })
        downloadTask.observe(.progress) { (snapshot) -> Void in
            // Download reported progress

            let percentComplete = 100 * Double(snapshot.progress!.completedUnitCount)
                / Double(snapshot.progress!.totalUnitCount)

            print(percentComplete)
            // Update the progress indicator
        }

        downloadTask.observe(.success) { (snapshot) -> Void in
            // Download completed successfully
            print("Download Success")
        } 
    } else {
        let image = UIImage(contentsOfFile: book.thumbImagePaht)
        self.imageView.image = image
        stopLoading();
    }
)

1 个答案:

答案 0 :(得分:2)

对我来说并不是什么可能是错的,但我看到一些可能导致问题的问题,最好修复它们:

在使用dequeueReusableCellWithIdentifier 的任何情况下,您都需要指定唯一且具有描述性的标识符。 “cell”不是一个好的标识符。

其次,当您创建新单元格时,需要为其指定一个重用标识符,以便以后可以将其出列。

第三,您没有遵循类的命名约定,即使用TitleCase。由于您命名为collectionViewCellBooks的类,因此理解您的代码更加困难。它应该被命名为BookViewCell或类似的东西。

第四,你的例子在你的Cell类中没有包含a prepareForReuse function,所以我假设你没有。您需要清除以前使用单元格的状态,因为正在重用单元对象。此函数的默认实现不执行任何操作,因此您需要填充它。

class BooksViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    override func collectionView(_ collectionView: UICollectionView,
                          cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let book = arrayBooks[indexPath.item]
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.BookCellReuseIdentifier,
                                                                      for: indexPath) as! BookViewCell
        cell.initWithBook(book: book)
        return cell
    }

    private struct Constants {
        static let BookCellReuseIdentifier = "BookCell"
    }
}

class BookViewCell: UICollectionViewCell {
    override func prepareForReuse() {
        // Remove any state in this cell that may be left over from its previous use.
        self.book = nil
        self.imageView.image = nil
        self.caption = nil
    }

    // Your initWithBook function goes here
}

This is a good tutorial关于使用UICollectionView。