【发布时间】:2020-07-07 16:24:52
【问题描述】:
我有一个应用程序,当用户为某个“挑战”提交图片时,它会从包含许多挑战列表的 collectionView 中删除该挑战。目前,为了确定完成了哪个挑战,我手动为直接对应于其索引的 7 个单元中的每一个分配了一个 ID(第一个单元的 ID 为 0,索引为 0)。有了这些信息,一旦我返回到带有 collectionView 的视图,它就会通过从数据数组中删除该项目并重新加载 collectionView 来删除该索引处的对象。问题是,一旦我删除了一个单元格,索引就会与原始索引/ID 不同,这意味着它之后会删除错误的单元格。
如何通过找到在 CustomCell 类中实现的单元格的唯一 ID 来确定实际删除哪个单元格。
在代码中,WeeklyViewController 是持有挑战集合视图的 VC。
import UIKit
struct CustomData {
var img: UIImage
var points: String
var mainLabel: String
var timeText: String
var score: String
var region: String
var lineStaticImage: UIImage
var subtitle: String
var challengeID: Int
}
class WeeklyViewController: UIViewController {
var n = Int()
var selImage = UIImage()
var recievedCompleteChallengeID = Int()
var recivedCompleteChallengeBool = Bool()
@IBOutlet weak var descLabel: UILabel!
var data = [CustomData]()
func completer() {
var masterchallengeList = ["Turn the lights of when you leave the room", "Turn the A/C off when you leave the house/room", "Compost your food from a couple of meals", "Don't let the run the water when brushing", "Walk, Bike, or Run to work, school, or your house", "Tell a friend to practice composting", "Take a walk around your neighborhood"]
var masterSubtitles = ["This week, whenever you leave the room, remember to take a look at the lights and determine whether they can be turned off...and then do it!", "When you leave your house or a section of your household, make it a point to turn off the fan/air-conditioning if it doesn't need to stay running", "Try looking up fun and interesting composting techniques and practice them with a few meal scraps", "Make sure to only use the water when you actually need it while brushing, and not when you are blankly staring into the mirror", "Try to avoid using your car or any mode of transport that uses gasoline; rather, hop on your bike, skateboard, or your own feet", "Once you figured out how you want to compost meal scraps, share it with a friend and ask them to send you a picture", "Many times, we forget that there can be an adventure other than our phones and computers, so open the door and go around your neighborhood" ]
data = [
CustomData(img: #imageLiteral(resourceName: "green"), points: "5", mainLabel: masterchallengeList[0], timeText: "⏰ Ends at midnight", score: "+\(Int.random(in: 1 ..< 50))", region: "Community", lineStaticImage: #imageLiteral(resourceName: "blueline"), subtitle: masterSubtitles[0], challengeID: 0),
CustomData(img: #imageLiteral(resourceName: "green"), points: "5", mainLabel: masterchallengeList[1], timeText: "⏰ Ends at midnight", score: "+\(Int.random(in: 1 ..< 50))", region: "Carbon Footprint", lineStaticImage: #imageLiteral(resourceName: "blueline"), subtitle: masterSubtitles[1], challengeID: 1),
CustomData(img: #imageLiteral(resourceName: "green"), points: "5", mainLabel: masterchallengeList[2], timeText: "⏰ Ends at midnight", score: "+\(Int.random(in: 1 ..< 50))", region: "Community", lineStaticImage: #imageLiteral(resourceName: "blueline"), subtitle: masterSubtitles[2],challengeID: 2),
CustomData(img: #imageLiteral(resourceName: "green"), points: "5", mainLabel: masterchallengeList[3], timeText: "⏰ Ends at midnight", score: "+\(Int.random(in: 1 ..< 50))", region: "Carbon Footprint", lineStaticImage:#imageLiteral(resourceName: "blueline"), subtitle: masterSubtitles[3],challengeID: 3),
CustomData(img: #imageLiteral(resourceName: "green"), points: "5", mainLabel: masterchallengeList[4], timeText: "⏰ Ends at midnight", score: "+\(Int.random(in: 1 ..< 50))", region: "Community", lineStaticImage: #imageLiteral(resourceName: "blueline"), subtitle: masterSubtitles[4],challengeID: 4),
CustomData(img: #imageLiteral(resourceName: "green"), points: "5", mainLabel: masterchallengeList[5], timeText: "⏰ Ends at midnight", score: "+\(Int.random(in: 1 ..< 50))", region: "Carbon Footprint", lineStaticImage: #imageLiteral(resourceName: "blueline"), subtitle: masterSubtitles[5],challengeID: 5)
]
}
fileprivate let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.register(CustomCell.self, forCellWithReuseIdentifier: "cell")
return cv
}()
override func viewDidLoad() {
super.viewDidLoad()
completer()
view.addSubview(collectionView)
collectionView.backgroundColor = .clear
collectionView.topAnchor.constraint(equalTo: descLabel.bottomAnchor, constant: 40).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -40).isActive = true
collectionView.contentInset.left = 20
collectionView.delegate = self
collectionView.dataSource = self
print(recivedCompleteChallengeBool)
print(recievedCompleteChallengeID)
}
override func viewDidAppear(_ animated: Bool) {
challengeRemover()
}
func challengeRemover() {
if recivedCompleteChallengeBool {
data.remove(at: recievedCompleteChallengeID)
collectionView.reloadData()
print("removed at \(recievedCompleteChallengeID)")
}
}
}
extension WeeklyViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 250, height: 400)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
cell.data = self.data[indexPath.row]
cell.backgroundColor = UIColor.init(red: 92, green: 219, blue: 149, alpha: 1)
cell.layer.cornerRadius = 30.0
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
n = indexPath.row
print("selected obj at \(n)")
performSegue(withIdentifier: "challengeSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var detailController = segue.destination as! SecondChallengeViewController
detailController.dataValues = "\(data[n])"
detailController.regionR = data[n].region
detailController.titleLabelLabel = data[n].mainLabel
detailController.points = data[n].score
detailController.subLabel = data[n].subtitle
detailController.receiverChallengeID = data[n].challengeID
}
@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {}
}
class CustomCell: UICollectionViewCell {
var id = Int()
var data: CustomData? {
didSet{
guard let data = data else { return }
bg.image = data.img
aa.text = data.mainLabel
timetext.text = data.timeText
scoreText.text = data.score
region.text = data.region
lineView.image = data.lineStaticImage
id = data.challengeID
}
}
fileprivate let bg: UIImageView = {
let iv = UIImageView()
iv.image = #imageLiteral(resourceName: "carousel3")
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.clipsToBounds = true
iv.layer.cornerRadius = 30.0
return iv
}()
fileprivate let aa: UILabel = {
let iv = UILabel()
iv.text = "furf"
iv.numberOfLines = 0
iv.font = UIFont.systemFont(ofSize: 22, weight: .bold)
iv.layer.frame = CGRect(x: 0, y: 0, width: 220, height: 100)
iv.translatesAutoresizingMaskIntoConstraints = false
iv.clipsToBounds = true
iv.isEnabled = true
iv.textColor = UIColor.init(red: 3/255, green: 29/255, blue: 59/255, alpha: 1)
iv.textAlignment = .natural
iv.sizeToFit()
iv.layer.backgroundColor = UIColor.clear.cgColor
return iv
}()
fileprivate let timetext: UILabel = {
let iv = UILabel()
iv.text = "timeText"
iv.numberOfLines = 0
iv.font = UIFont.systemFont(ofSize: 14, weight: .regular)
iv.layer.frame = CGRect(x: 0, y: 0, width: 220, height: 30)
iv.textColor = UIColor.init(red: 3/255, green: 29/255, blue: 59/255, alpha: 1)
iv.translatesAutoresizingMaskIntoConstraints = false
iv.clipsToBounds = true
iv.textAlignment = .natural
iv.sizeToFit()
iv.layer.backgroundColor = UIColor.clear.cgColor
return iv
}()
fileprivate let scoreText: UILabel = {
let iv = UILabel()
iv.text = "scoreText"
iv.textColor = UIColor.init(red: 3/255, green: 29/255, blue: 59/255, alpha: 1)
iv.numberOfLines = 0
iv.font = UIFont.systemFont(ofSize: 20, weight: .bold)
iv.layer.frame = CGRect(x: 0, y: 0, width: 220, height: 50)
iv.translatesAutoresizingMaskIntoConstraints = false
iv.clipsToBounds = true
iv.textAlignment = .natural
iv.sizeToFit()
iv.layer.backgroundColor = UIColor.clear.cgColor
return iv
}()
fileprivate let region: UILabel = {
let iv = UILabel()
iv.text = "regionText"
iv.textColor = UIColor.init(red: 3/255, green: 29/255, blue: 59/255, alpha: 1)
iv.numberOfLines = 0
iv.font = UIFont.systemFont(ofSize: 15, weight: .light)
iv.layer.frame = CGRect(x: 0, y: 0, width: 220, height: 50)
iv.translatesAutoresizingMaskIntoConstraints = false
iv.clipsToBounds = true
iv.textAlignment = .natural
iv.sizeToFit()
iv.layer.backgroundColor = UIColor.clear.cgColor
return iv
}()
fileprivate let lineView: UIImageView = {
let iv = UIImageView()
iv.layer.frame = CGRect(x: 0, y: 0, width: 250, height: 20)
iv.contentMode = .scaleToFill
iv.translatesAutoresizingMaskIntoConstraints = false
iv.clipsToBounds = true
iv.sizeToFit()
return iv
}()
fileprivate let line2View: UIImageView = {
let iv = UIImageView()
iv.layer.frame = CGRect(x: 0, y: 0, width: 250, height: 20)
iv.contentMode = .scaleToFill
iv.translatesAutoresizingMaskIntoConstraints = false
iv.clipsToBounds = true
iv.sizeToFit()
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.addSubview(bg)
self.contentView.addSubview(aa)
self.contentView.addSubview(timetext)
self.contentView.addSubview(scoreText)
self.contentView.addSubview(region)
self.contentView.addSubview(lineView)
self.contentView.addSubview(line2View)
bg.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true
bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true
bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
aa.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 40).isActive = true
aa.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15).isActive = true
aa.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -260).isActive = true
aa.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15).isActive = true
timetext.topAnchor.constraint(equalTo: aa.bottomAnchor, constant: 230).isActive = true
timetext.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15).isActive = true
timetext.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10).isActive = true
timetext.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15).isActive = true
scoreText.topAnchor.constraint(equalTo: aa.bottomAnchor, constant: 30).isActive = true
scoreText.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15).isActive = true
scoreText.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15).isActive = true
region.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 25).isActive = true
region.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15).isActive = true
region.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15).isActive = true
lineView.topAnchor.constraint(equalTo: scoreText.bottomAnchor, constant: 140).isActive = true
lineView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
lineView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
line2View.topAnchor.constraint(equalTo: scoreText.bottomAnchor, constant: 137).isActive = true
line2View.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
line2View.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
具有每个挑战的详细视图的 VC 在这里可以选择和提交图片:
class SecondChallengeViewController: UIViewController{
var dataValues = String()
var points = String()
var titleLabelLabel = String()
var regionR = String()
var subLabel = String()
var receiverChallengeID = Int()
var challengeComp = Bool()
@IBOutlet weak var submitButton: UIButton!
@IBOutlet weak var submittedPicture: UIImageView!
@IBOutlet weak var challengeTitle: UILabel!
var selImage = UIImage()
@IBOutlet weak var subtitleLabel: UILabel!
@IBOutlet weak var regionLabel: UILabel!
@IBOutlet weak var pointstogiveLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
assignValues()
print(dataValues)
print(points)
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Dashboard"
navigationController?.navigationBar.barStyle = .default
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
}
func assignValues() {
regionLabel.text = regionR
challengeTitle.text = titleLabelLabel
pointstogiveLabel.text = "\(points) evoPoints"
subtitleLabel.text = subLabel
}
@IBAction func cameraTapped(_ sender: Any) {
presentPhotoActionSheet()
}
func setSubmittedPicture() {
submittedPicture.image = selImage
submittedPicture.layer.cornerRadius = 20
submitButton.layer.cornerRadius = 25.0
submitButton.alpha = 1
}
func showToast(controller: UIViewController, message : String, seconds: Double) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
alert.view.backgroundColor = UIColor.black
alert.view.alpha = 0.6
alert.view.layer.cornerRadius = 15
controller.present(alert, animated: true)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) {
alert.dismiss(animated: true)
}
}
@IBAction func submitTapped(_ sender: Any) {
if(submittedPicture != nil){
challengeCompleted()
}
}
func challengeCompleted() {
showToast(controller: self, message: "You Successfully Completed a Challenge", seconds: 2)
submitButton.alpha = 0
submittedPicture.alpha = 0
challengeComp = true
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var challengePanelVC = segue.destination as! WeeklyViewController
if(challengeComp){
challengePanelVC.recievedCompleteChallengeID = receiverChallengeID
challengePanelVC.recivedCompleteChallengeBool = challengeComp
}
}
}
extension SecondChallengeViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func presentPhotoActionSheet() {
let actionSheet = UIAlertController(title: "Challenge Picture", message: "How would share your challenge with us", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
actionSheet.addAction(UIAlertAction(title: "Take Photo", style: .default, handler: { [weak self] _ in
self?.presentCamera()
}))
actionSheet.addAction(UIAlertAction(title: "Choose Photo", style: .default, handler: { [weak self] _ in
self?.presentPhotoPicker()
}))
present(actionSheet, animated: true)
}
func presentCamera() {
let vc = UIImagePickerController()
vc.sourceType = .camera
vc.delegate = self
vc.allowsEditing = true
present(vc, animated: true)
}
func presentPhotoPicker(){
let vc = UIImagePickerController()
vc.sourceType = .photoLibrary
vc.delegate = self
vc.allowsEditing = true
present(vc, animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let selectedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else{
return}
selImage = selectedImage
setSubmittedPicture()
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
override func present(_ viewControllerToPresent: UIViewController,
animated flag: Bool,
completion: (() -> Void)? = nil) {
viewControllerToPresent.modalPresentationStyle = .fullScreen
super.present(viewControllerToPresent, animated: flag, completion: completion)
}
}
我怎样才能确定我必须删除哪张卡?
【问题讨论】:
标签: ios swift uicollectionview uicollectionviewcell