Swift Добавление различных действий к ячейкам в UICollectionView

Я не знаю, с чего начать, у меня есть UICollectionView с несколькими ячейками, заполненными UIImage. Я хочу, чтобы каждая ячейка/UIImage выполняла различное действие при касании пальцем. Может ли кто-нибудь указать мне правильное направление здесь?

Действие, которое у меня есть, - это @IBAction из UIButton, я знаю, что хочу, чтобы это действие было в ячейке в UICollectionView..

(Думаю, мне нужно что-то сделать с «let cell = countryCollectionView.dequeueReusableCell»?

import UIKit

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

    @IBOutlet weak var soundsCollectionView: UICollectionView!
    
    lazy var cv: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical
        
    var cc = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cc.translatesAutoresizingMaskIntoConstraints = false
    cc.register(CustomCell.self, forCellWithReuseIdentifier: "CustomCell")
    cc.delegate = self
    cc.dataSource = self
    cc.backgroundColor = .white
    return cc
    }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            
            view.addSubview(cv)
            cv.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
            cv.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
            cv.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
            cv.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
            
        }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
        cell.tag = indexPath.row
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: 100)
    }
    
}

class CustomCell: UICollectionViewCell {
    
    lazy var centerImageView: UIImageView = {
        var img = UIImageView()
        img.translatesAutoresizingMaskIntoConstraints = false
        img.image = UIImage(named: "1")
        img.clipsToBounds = true
        img.isUserInteractionEnabled = true
        
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handler(_:)))
        tapGesture.numberOfTapsRequired = 1
        
        img.addGestureRecognizer(tapGesture)
        
        return img
    }()
    
    @objc private func handler(_ sender: UITapGestureRecognizer) {
        print("tapped tag > ", self.tag)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        addSubview(centerImageView)
        centerImageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        centerImageView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
        centerImageView.heightAnchor.constraint(equalToConstant: 80).isActive = true
        centerImageView.widthAnchor.constraint(equalToConstant: 80).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

person DeDe Schurk    schedule 11.07.2020    source источник
comment
эй Деде это сработало для вас?   -  person eemrah    schedule 12.07.2020
comment
Здравствуйте элия, спасибо за ответ! Я немного борюсь. Я обновил метод 'cellForItemAt' и добавил его в свой soundCell.swift (класс UICollectionViewCell?) @IBAction func sound1(_ sender: UIButton) { if (self.tag == 0) { // I am first cell, so act like this. } else if (self.tag == 1) { // Second cell blah blah } } Но как мне настроить каждую ячейку по-разному, чтобы что-то делать одним касанием? Например image1: print (я кнопка 1) И image2: print (я кнопка 2) Еще раз, спасибо за ваше время! Очень ценится   -  person DeDe Schurk    schedule 13.07.2020
comment
привет еще раз, используйте UITapGestureRecognizer для UIImageView в UICollectionViewCell. В жесте касания #action отметьте self.tag, чтобы вы могли обработать это, если tag == 0 это изображение первой ячейки. а если tag == 3 это 4. ячейка. Вы не возражали?   -  person eemrah    schedule 13.07.2020
comment
Ну, последние 48 часов я пытался понять, что вы имеете в виду, я действительно пытаюсь заставить это работать и провести собственное исследование, прежде чем задавать здесь глупые вопросы: P. Я добавил этот let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped)) tap.numberOfTapsRequired = 2 view.addGestureRecognizer(tap) в свой ViewController (viewDidLoad). И @objc func doubleTapped() { // do something here } Но я не понимаю, что вы имеете в виду под self.tag. Я на правильном пути с приведенным выше кодом? Еще раз спасибо Элия!   -  person DeDe Schurk    schedule 15.07.2020
comment
эй, @Dede, ты можешь назначить UICollectionViewCell тегу, и этот тег поможет тебе, какая ячейка является элементом внутри UICollectionViewCell. Я редактирую свой ответ в качестве примера для вас   -  person eemrah    schedule 15.07.2020
comment
@elia, я приближаюсь! :) Но когда я запускаю приложение, экран весь белый. Но когда я случайно нажимаю на экран, я вижу тег Tapped › 1 или 2 и т. д. на выходе консоли. Так что это работает, но я не вижу изображения. Я думаю, что удалил часть своего исходного кода. Я обновил свой код в своем первом посте, чтобы вы могли видеть, что у меня есть сейчас. Вы видите, чего не хватает? Спасибо еще раз!! (И извините за мой поздний ответ).   -  person DeDe Schurk    schedule 20.07.2020
comment
если вы используете строку img.image = UIImage(named: "1") для кода, эта строка говорит, что у вас должно быть изображение с именем 1 . поэтому вы должны использовать свои собственные имена изображений, возможно?   -  person eemrah    schedule 20.07.2020
comment
@elia Конечно .. это работает ..! Но.. Как настроить несколько изображений? Допустим, у меня есть 10 разных изображений.. :/   -  person DeDe Schurk    schedule 20.07.2020
comment
Предположим, что у вас есть массив let imageArray = [UIImage(named:"first"),UIImage(named:"second"),UIImage(named:"third"),UIImage(named:"fourth")] и в методе cellForRow вам нужно вызвать myCell.imageView.image = imageArray[indexPath.row] или то, как вы обрабатываете свою ячейку. Для моего примера в ответе это должно быть cell.centerImageView.image = imageArray[indexPath.row]. вам нужно выяснить, что ``numberOfCount` должно равняться imageArray count   -  person eemrah    schedule 20.07.2020
comment
@elia Я понимаю, но cellForRow ? у меня нет..? Вы имеете в виду cellForItemAt ?   -  person DeDe Schurk    schedule 20.07.2020
comment
да, я имею в виду метод cellForItemAt :)   -  person eemrah    schedule 20.07.2020
comment
Хммм, получение Невозможно присвоить значение типа "String" для типа "UIImage" func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell cell.centerImageView.image = countries[indexPath.row] cell.tag = indexPath.row return cell }   -  person DeDe Schurk    schedule 20.07.2020
comment
Давайте продолжим обсуждение в чате.   -  person eemrah    schedule 20.07.2020


Ответы (2)


Я редактирую как новый программный пример для решения вашей проблемы.

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    
    lazy var cv: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        
        var cc = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cc.translatesAutoresizingMaskIntoConstraints = false
        cc.register(CustomCell.self, forCellWithReuseIdentifier: "CustomCell")
        cc.delegate = self
        cc.dataSource = self
        cc.backgroundColor = .white
        return cc
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(cv)
        cv.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        cv.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        cv.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        cv.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }
    
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
        cell.tag = indexPath.row
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: 100)
    }
    
    
}


class CustomCell: UICollectionViewCell {
    
    lazy var centerImageView: UIImageView = {
        var img = UIImageView()
        img.translatesAutoresizingMaskIntoConstraints = false
        img.image = UIImage(named: "1")
        img.clipsToBounds = true
        img.isUserInteractionEnabled = true
        
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handler(_:)))
        tapGesture.numberOfTapsRequired = 1
        
        img.addGestureRecognizer(tapGesture)
        
        return img
    }()
    
    @objc private func handler(_ sender: UITapGestureRecognizer) {
        print("tapped tag > ", self.tag)
    }
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        
        
        addSubview(centerImageView)
        centerImageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        centerImageView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
        centerImageView.heightAnchor.constraint(equalToConstant: 80).isActive = true
        centerImageView.widthAnchor.constraint(equalToConstant: 80).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
person eemrah    schedule 11.07.2020
comment
эй, @DeDeSchurk, ты построил его? - person eemrah; 13.07.2020

В этом случае я бы не стал использовать кнопки на ваших ячейках. Вместо этого вам следует подключиться к метод делегата didSelectItemAt и просто добавить необходимые информацию в модель данных:

struct Country {
    let imageName: String
    let sound: Sound // You didn't specify what type the sound1 object is but you get the gist
}

Таким образом, массив ваших стран теперь будет содержать эту новую структуру, а не просто необработанные строки:

let countries = [
    Country("country1", sound1),
    Country("country2", sound2),
    ...
]

Затем вы можете получить точный звук, который хотите воспроизвести, из indexPath, переданного в didSelectItemAt:

let sound = self.countries[indexPath.row].sound
sound.play()

Вам также нужно настроить способ установки изображения ячейки в cellForItemAt:

let imageName = self.countries[indexPath.row].imageName
cell.countryImageView.image = UIImage(named: imageName)
person WongWray    schedule 15.07.2020