【问题标题】:UICollectionView Functionality issuesUICollectionView 功能问题
【发布时间】:2016-03-09 17:31:40
【问题描述】:

我在 VC1 上有一个 UICollectionViewCell,该单元格包含一个图像、一个标签和 3 个按钮。

当我点击单元格时。这会触发我的didSelectItemAtIndexPath 将我带到编辑项目屏幕。

如何访问每个按钮并将其与我单击的单元格相关联?

因此,如果我添加了 6 个单元格,然后单击单元格 1、按钮 1,它会将我带到一个包含该人信息的简历页面。如果我单击单元格 2 按钮 1,它会将我带到相同的 bio VC,但与我单击的单元格相关的信息不同。

我的困惑在于在哪里或如何设置它?

谢谢!

    import UIKit
    import Parse


    class TrainersViewController: UIViewController,         UICollectionViewDataSource, UICollectionViewDelegate, AddNewTrainerViewControllerDelegate {

var trainers: [TrainerArray]


required init?(coder aDecoder: NSCoder) {
    trainers = [TrainerArray]()
    super.init(coder: aDecoder)
    loadTrainerItems()
}

//connection to the collection view
@IBOutlet weak var collectionView: UICollectionView!


func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
   print("selected")
   saveTrainerItems()

}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

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

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

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TrainerCell", forIndexPath: indexPath)
    var buttonOne = cell.viewWithTag(10)
    buttonOne = indexPath.row



    let trainer = trainers[indexPath.row]
    configureTrainerForCell(cell, withTrainerArray: trainer)
    return cell
}


func configureTrainerForCell(cell: UICollectionViewCell, withTrainerArray trainer: TrainerArray) {

    if trainer.trainerImage == nil {

        let label = cell.viewWithTag(1000) as! UILabel
        trainer.trainerImage = UIImage(named: "defaultImage")
        label.text = trainer.name

    } else {
    let image = cell.viewWithTag(2000) as! UIImageView
    image.image = trainer.trainerImage

    let label = cell.viewWithTag(1000) as! UILabel
    label.text = trainer.name
}
}


override func viewDidLoad() {
    super.viewDidLoad()
   }


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

//This method adds a new trainer to the trainer array
func addNewTrainerViewController(controller: AddNewTrainerViewController, didFinishAddingItem item: TrainerArray) {

    let newRowIndex = trainers.count
    trainers.append(item)

    let indexPath = NSIndexPath(forRow: newRowIndex, inSection: 0)
    let indexPaths = [indexPath]
    collectionView.insertItemsAtIndexPaths(indexPaths)

    dismissViewControllerAnimated(true, completion: nil)
    saveTrainerItems()

}

func addNewTrainerViewController(controller: AddNewTrainerViewController, didFinishDeletingItem item: TrainerArray) {

    if let index = trainers.indexOf(item) {

        let indexPath = NSIndexPath(forRow: index, inSection: 0)
        let indexPaths = [indexPath]
        if let _ = collectionView.cellForItemAtIndexPath(indexPath) {

            self.trainers.removeAtIndex(index)
            self.collectionView.deleteItemsAtIndexPaths(indexPaths)

        }
    }
        dismissViewControllerAnimated(true, completion: nil)
        saveTrainerItems()
}

//This Method Edits a Trainer
func addNewTrainerViewController(controller: AddNewTrainerViewController, didFinishEditingItem trainer: TrainerArray) {

    if let index = trainers.indexOf(trainer) {

        let indexPath = NSIndexPath(forRow: index, inSection: 0)
        if let cell = collectionView.cellForItemAtIndexPath(indexPath){

            configureTrainerForCell(cell, withTrainerArray: trainer)
        }
    }
    saveTrainerItems()
    dismissViewControllerAnimated(true, completion: nil)
}


func addNewTrainerViewControllerDidCancel(controller: AddNewTrainerViewController) {
    dismissViewControllerAnimated(true, completion: nil)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "AddTrainer" {

        let navigationController = segue.destinationViewController as! UINavigationController
        let controller = navigationController.topViewController as! AddNewTrainerViewController
        controller.delegate = self

    } else if segue.identifier == "EditTrainer" {

        let navigationController = segue.destinationViewController as! UINavigationController
        let controller = navigationController.topViewController as! AddNewTrainerViewController
        controller.delegate = self

        if let indexPath = collectionView.indexPathForCell(sender as! UICollectionViewCell) {

            controller.trainerToEdit = trainers[indexPath.row]
        }
    }
}



func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
}

func documentsDirectory() -> String {

    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    return paths[0]
}


func dataFilePath() -> String {

    return (documentsDirectory() as NSString)
                            .stringByAppendingPathComponent("Trainers.plist")
}

func saveTrainerItems() {

    let data = NSMutableData()
    let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
    archiver.encodeObject(trainers, forKey: "TrainersArray")
    archiver.finishEncoding()
    data.writeToFile(dataFilePath(), atomically: true)
}

func loadTrainerItems() {

    let path = dataFilePath()
    if NSFileManager.defaultManager().fileExistsAtPath(path) {

        if let data = NSData(contentsOfFile: path) {

            let unarchiver = NSKeyedUnarchiver(forReadingWithData: data)
            trainers = unarchiver.decodeObjectForKey("TrainersArray") as! [TrainerArray]
            unarchiver.finishDecoding()
        }
    }
}


@IBAction func logOut(sender: AnyObject) {

        let alert = UIAlertController(title: "Are You Sure You Want To Log Out?", message: "Please Enter Your Username", preferredStyle: UIAlertControllerStyle.Alert)

        alert.addTextFieldWithConfigurationHandler { (textField) -> Void in
        }

    alert.addAction(UIAlertAction(title: "Log Out", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
        let textF = alert.textFields![0] as UITextField

        if textF.text! != PFUser.currentUser()?.username {
            self.displayGenericAlert("Incorrect Username!", message: "Please Enter a Valid Username")

        } else if textF.text! == PFUser.currentUser()?.username {
           PFUser.logOut()
           _ = PFUser.currentUser()
        self.dismissViewControllerAnimated(true, completion: nil)
        }
    }))

    alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
        if action == true {
        self.dismissViewControllerAnimated(false, completion: nil)
        }}))

self.presentViewController(alert, animated: true, completion: nil)

}

func displayGenericAlert(title: String, message: String) {

    let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { (action) -> Void in
    }))
    self.presentViewController(alert, animated: true, completion: nil)
}

@IBAction func bioSegueButton(sender: AnyObject) {

}

}

【问题讨论】:

    标签: ios swift uibutton uicollectionview uicollectionviewcell


    【解决方案1】:

    您可以将标签添加到与所在单元格的索引相对应的按钮上。在cellForItemAtIndexPath 中,您可以添加类似...

    button.tag = indexPath.row
    

    在按钮的选择器中,您可以访问它...

    func buttonSelector(sender: UIButton) {
        let index = sender.tag
        let trainer = trainers[index]
    }
    

    编辑:

    您可能在 cellForRowAtIndexPath 中执行的操作的更完整版本:

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TrainerCell", forIndexPath: indexPath) as? MyCollectionViewCell
        var buttonOne = cell?.button1
        buttonOne?.tag = indexPath.row
    
        let trainer = trainers[indexPath.row]
        configureTrainerForCell(cell, withTrainerArray: trainer)
        return cell!
    }
    

    您的集合视图单元格类:

    class MyCollectionViewCell: UICollectionViewCell {
        @IBOutlet weak var button1: UIButton! // connect this to the button in your interface builder's collection view cell.
    
        // Do the same for any other subviews.
    }
    

    同样在界面生成器中,将集合视图单元原型的类更改为这个新的自定义类。

    【讨论】:

    • 我明白了。我现在要试一试,很快就会回来报告!
    • 我似乎无法让它工作。我已经发布了上面cellForItemAtIndexPath 的代码。
    • 您似乎已经在使用标签来获取您想要的按钮。我建议使用自定义单元格中的属性直接访问按钮。然后,您可以为该按钮分配一个标签。稍后调用它的选择器时,该标签将对应于 indexPath.row,然后您可以访问正确的数据,但会保留这些数据。我将尝试编辑以显示此内容。
    • 好的,我只在你告诉我要执行 button.tag = indexPath.row 之后添加了 let buttonOne = cell.viewWithTag(10) 现在,如果我尝试调用 buttonOne = indexPath.row 我得到错误“无法将 int 类型的值分配给值输入UIView?
    • 我没有class MyCollectionViewCell... 我在我的主要VC 中调用collectionViewCell 的所有方法......我是swift 新手。我已经为我的 VC 添加了代码,你能告诉我什么需要移到 custom class 中吗?
    【解决方案2】:

    您可以从索引 'indexpath.row' 的数组中获取数据。

    【讨论】:

    • 我明白了,我现在是否应该在两个 VC 之间链接一个协议和委托,以便能够从 TrainerCell 向 BioVC 发送信息
    • 如果您正在通过 Segue 导航,那么您可以在 prepareForSegue 方法中传递数据,否则委托是您的选择。
    猜你喜欢
    • 2016-09-06
    • 2012-09-15
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多