做一个界面的时候,虽然很简单,但是有个地方还是卡了很久,今天做一个总结,帮助记忆和梳理知识点
首先效果图一个界面:
选择后是这个样式:
总来说界面简单,自己主要卡在了cell的重用上面了,在选择图片之后,将界面拖动到下面会出现:
1.下面的图片会被选中
2.拖会顶部之前选择的图片会取消选中
等等。。。。
这就是cell重用机制导致的一些问题,在谷歌上找了很久没有合适的方法,百度更别说了。。。。下面介绍一下自己的解决方案:
首先明确一下思路:
1.创建saveImagesArray数组用来保存选中的图片var saveImages = [NSURL]()
2.创建indexPathDic字典用来保存选中的indexPath的值var indexPathDic = [Int : NSIndexPath]()
3.实现代理方法func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
然后,我们上代码,然后再解释:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! BrowserImagesCell
update(cell: cell, atIndexPath: indexPath)
return cell
}
这个方法相信都不陌生,在这个方法中我自己定义了一个update(cell: cell, atIndexPath: indexPath)
的方法就是更新cell中属性
func update(cell cell:BrowserImagesCell, atIndexPath: NSIndexPath) {
cell.imagesView.sd_setImageWithURL(imagesArray[atIndexPath.row])
if saveImages.count > 0 {
saveImagesButton.enabled = true
} else {
saveImagesButton.enabled = false
}
let key = atIndexPath.row
if indexPathDic[key] == nil {
cell.checkButton.hidden = true
cell.selected = false
} else if indexPathDic[key]?.row == atIndexPath.row {
cell.checkButton.hidden = false
cell.selected = true
saveImages.append(imagesArray[atIndexPath.row])
}
}
这个就是那个更新cell的代码,在这个方法中要根据indexPathDic
中的key对应的值来决定cell被选中和取消选中的样式。其中我使用一个button来设置checkMark的,button中设置一个默认图片,默认被隐藏,当被选中的时候取消隐藏,saveImagesButton
这个按钮就是界面右上角要用到的保存图片的按钮当我们的数组中没有要图片的时候,就让它的可编辑属性为false。最开始的cell.imagesView.sd_setImageWithURL(imagesArray[atIndexPath.row]
这里可以忽略,只是我用第三方库来加载图片用的。这里要保存的并不是图片本身,而是图片的URL,让后用第三方库来加载URL获取图片。
啰嗦的再说明一下这几个判断indexPathDic[key] == nil
if indexPathDic[key]?.row == atIndexPath.row
这2个判断就是:
1.如果字典中没有key对应的indexPath值的话要做的事情
2.如果字典中有key对用的indexPath的值,并取出row 如果和当前选中的cell的indexPath.row一样的话要做的事情【显示选中,保存图片】这里有个cell.selected = true
这个后面说明,这就是设置为true
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let key = indexPath.row
if indexPathDic[key] == nil {
indexPathDic[key] = indexPath
} else {
indexPathDic.removeValueForKey(key)
}
if saveImages.count > 0 {
saveImages.removeAll()
}
collectionView.reloadData()
}
这个方法是点击选择cell的时候会被调用
其中有这几个判断:indexPathDic[key] == nil
saveImages.count > 0
首先,判断字典中key对应的值是否存在,如果不存在,将其保存到字典中去,第二个判断就是,保存图片的数组中是否有值,如果有清空,最后一步就是刷新表格.完工!这个就已经解决了重用的问题了,下面就是一些细节和样式的处理了。
图片保存:
@IBAction func saveImages(sender: UIBarButtonItem) {
for img in saveImages {
let imageURL = DecoImage()
imageURL.identifier = img.absoluteString
realm.write {
self.decoFolder.images.append(imageURL)
}
}
dismissViewControllerAnimated(true, completion: nil)
}
给保存按钮添加点击事件,然后在这里循环遍历图片数组中的内容,并写入数据库,这里我是用的realm数据库做的,道理是一样的。就是存数据
再说明一下cell中的设置:
弄这样的界面肯定会有个自定义的cell类
其中有这几个细节,在用storyboard搭建界面运用autoLayout的时候,我们在刷新控件要调用的方法如下:
override var selected: Bool {
didSet {
setNeedsUpdateConstraints()
}
}
复写selected这个属性,并监听它触发setNeedsUpdateConstraints()
这个方法。
override func updateConstraints() {
super.updateConstraints()
if selected {
self.layer.borderWidth = 3
self.layer.borderColor = UIColor(red: 0/255.0, green: 92/255.0, blue: 255/255.0, alpha: 0.8).CGColor
} else {
self.layer.borderWidth = 0
self.layer.borderColor = nil
}
}
之后复写这个方法,在这里进行对前面说的selected的判断,设置对应cell的样式。
通过这个学到了不少东西,而且解除了collectionView的方便之处,而且还有个单选的方法有时间可以去研究一下:func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath)