简体   繁体   English

UIButton的.touchUpInside事件不起作用

[英]UIButton's .touchUpInside event not working

I am working on adding buttons to UICollectionViewCell at runtime and having the button registered to the event according to its type, at runtime. 我正在努力在运行时向UICollectionViewCell添加按钮, UICollectionViewCell在运行时根据事件的类型将按钮注册到事件。 The type of the button can be, for instance, utterance button and action button, and both should be registered to separate events. 按钮的类型可以是例如发声按钮和操作按钮,并且应该将两者注册为单独的事件。

The hierarchy of UI elements is like UICollectionView -> UICollectionViewCell -> StackView -> Multiple ( UIView -> UIButton ). UI元素的层次结构是像UICollectionView - > UICollectionViewCell - > StackView - >海报( UIView - > UIButton )。

The problem is that I am unable to register the .touchUpInside events. 问题是我无法注册.touchUpInside事件。

What I have tried yet is calling becomeFirstResponder() through button's instance, moving the event method inside the UIViewController and adding target in cellForItemAt method after having the view hierarchy set up, trying isUserInteractionEnabled with values true and false on UICollectionView , UICollectionViewCell , UIStackView , UIView and UIButton . 我已经试过没被调用becomeFirstResponder()通过按钮的情况下,移动内部的事件方法UIViewController并添加目标cellForItemAt具有视图层次建立,努力之后方法isUserInteractionEnabled与价值观truefalseUICollectionViewUICollectionViewCellUIStackViewUIViewUIButton

EDIT 1: So the code looks like the following: 编辑1:因此,代码如下所示:

class AssistantViewController: UIViewController {
    private var assistantManager: AssistantManager
    private var conversationSection: UICollectionView
    private let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init()

    private var multipleChoiceMessageCell = MultipleChoiceMessageCell()
    private var conversationCells: [BaseCollectionViewCell] {
        return [
            multipleChoiceMessageCell
        ]
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        construct()
        assistantManager.performGreetingUtterance()
    }

}

extension AssistantViewController: UICollectionViewDataSource {
    @objc func didTapUtteranceButton() {
        print ("elo I a m here")
    }

    func collectionView(_ collectionView: UICollectionView,
                        cellForItemAt indexPath: IndexPath) -> 
  UICollectionViewCell {
        let conversationItem = assistantManager.conversationItems[indexPath.row]
        let cellId = self.getCellIdentifier(for: conversationItem)
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId,
                                                      for: indexPath) as? ConversationItemCell

        if let conversationCell = cell {
            conversationCell.layoutIfNeeded()

            conversationCell.configure(with: conversationItem)

            switch conversationItem {
            case let .multipleChoiceMessage(chatMessage, multipleChoice): do {

                for item in multipleChoice.multipleChoice.items {
                    switch item {
                    case .utteranceButton(let utteranceButton): do {
                        utteranceButton.button.isUserInteractionEnabled = true
                        utteranceButton.button.addTarget(self,
                                                         action: #selector(didTapUtteranceButton),
                                                         for: .touchUpInside)
                        //utteranceButton.button.becomeFirstResponder()
                        print("added")
                        }
                    }
                }
                }
            default: print("Todo")
            }
        }
        return cell!
    }

class AssistantManager {
    public func parseAssistantSnippets(
        snippets: [Snippet]) -> ConversationCellModel {
        var interactableItems: [MessageContent] = []
        var utteredText:String = ""

        for snippet in snippets {
            switch snippet {
            case .text(let text): utteredText = text.displayText
            case .utteranceButton(let utteranceButton): do {
                let button = UtteranceButton(buttonTitle: utteranceButton.displayText,
                                               maxWidth: ConversationCell.elementMaxWidth,
                                               utteranceText: utteranceButton.utteranceText,
                                               onPress: performUserUtterance)
                let messageContent = MessageContent.utteranceButton(button)

                interactableItems.push(messageContent)
                }
            default: print("TODO")
            }
        }
        return  ConversationCellModel.init(message: utteredText,
                                           multipleChoice: interactableItems)
    }

    public func performGreetingUtterance() {
        self.addTypingIndicator()

        performUtteranceOperation(utterance: "hi")
    }

    public func performUtteranceOperation(utterance: String) {
        let context = UtteranceRequest.UserContext(cid: "1",
                                                   location: CLLocationCoordinate2D(),
                                                   storeID: "1",
                                                   timeZoneOffset: 0)
        let request = UtteranceRequest(utterance: utterance,
                                       context: context)

        provider.conveyUtterance(request) { [weak self] result in
            switch result {
            case .success(let snippetResponse): do {
                let snippetResponseTransformed = SnippetResponse.init(snippetResponse)
                let ConversationCellModel = self?.parseAssistantSnippets(
                    snippets: snippetResponseTransformed.snippets)

                if let model = ConversationCellModel {
                    self?.addMessageFromAssistant(interactableItems: model.multipleChoice,
                                                       utteredText: model.message)
                }
                }
            case .failure(let error): return
            }
        }
    }
}

class MultipleChoiceMessageCell: ConversationCell {
    public func configure(with conversationItem: ConversationItem) {
        switch conversationItem {
        case let .multipleChoiceMessage(chatMessage, multipleChoice): do {
            let isCellFromUser = chatMessage.metadata.isFromUser
            let avatarBackgroundColor = chatMessage.metadata.avatarBackgroundColor
            let avatarTintColor = chatMessage.metadata.avatarTintColor
            let messageTextBackgroundColor = chatMessage.metadata.textContainerBackgroundColor
            let messageTextColor = chatMessage.metadata.textColor

            self.messageTextLabel.text = chatMessage.message
            self.avatarImageView.image = chatMessage.metadata.avatarImage
            self.messageTextContainer.backgroundColor = messageTextBackgroundColor
            self.messageTextLabel.textColor = messageTextColor
            self.avatarImageView.backgroundColor = avatarBackgroundColor
            self.avatarImageView.tintColor = avatarTintColor
            self.rightMessageHorizontalConstraint?.isActive = isCellFromUser
            self.leftMessageHorizontalConstraint?.isActive = !isCellFromUser
            self.rightAvatarHorizontalConstraint?.isActive = isCellFromUser
            self.leftAvatarHorizontalConstraint?.isActive = !isCellFromUser

            configureCellWith(interactablesSection: multipleChoice.multipleChoice.itemsContainer)
        }
        default:
            logIncorrectMapping(expected: "message", actual: conversationItem)
        }
    }

    func configureCellWith(interactablesSection: UIStackView) {
        let stackViewTop = NSLayoutConstraint(
            item: interactablesSection,
            attribute: .top,
            relatedBy: .equal,
            toItem: self.messageTextContainer,
            attribute: .bottom,
            multiplier: 1,
            constant: 10)
        let stackViewLeading = NSLayoutConstraint(
            item: interactablesSection,
            attribute: .leading,
            relatedBy: .equal,
            toItem: self,
            attribute: .leading,
            multiplier: 1,
            constant: ConversationCell.avatarMaxSize +
                ConversationCell.messageContainerMaxLeadingMargin +
                ConversationCell.avatarMaxMargin)

        self.addAutoLayoutSubview(interactablesSection)

        self.addConstraints([stackViewTop,
                             stackViewLeading])
    }
}

class InteractableItem {
    let contentView: UIView
    var height: CGFloat

    init() {
        contentView = UIView()
        height = 0
    }
}

class CellPrimaryButton: InteractableItem {
    let button: CorePrimaryButton

    init(buttonTitle titleLabel: String, maxWidth: CGFloat) {
        button = CorePrimaryButton()
        button.setTitle(titleLabel, for: .normal)
        button.setBackgroundColor(CoreColor.white, for: .normal)
        button.setTitleColor(CoreColor.black, for: .normal)
        button.layer.borderColor = CoreColor.black.cgColor
        button.layer.borderWidth = 1
        //button.becomeFirstResponder()
        super.init()
        contentView.isUserInteractionEnabled = true
//        button.addTarget(self, action: #selector(didTapUtteranceButton), for: .touchUpInside)
        setConstraints(maxWidth: maxWidth)
    }

    func setConstraints(maxWidth: CGFloat) {
        let buttonHorizontal = NSLayoutConstraint(item: self.button,
                                                  attribute: .leading,
                                                  relatedBy: .equal,
                                                  toItem: self.contentView,
                                                  attribute: .leading,
                                                  multiplier: 1,
                                                  constant: 0)

        let buttonWidth = NSLayoutConstraint(item: self.button,
                                              attribute: .width,
                                              relatedBy: .lessThanOrEqual,
                                              toItem: nil,
                                              attribute: .notAnAttribute,
                                              multiplier: 1,
                                              constant: maxWidth)

        self.contentView.addConstraints([buttonHorizontal,
                                         buttonWidth])
        self.contentView.backgroundColor = UIColor.purple
        self.height = self.button.intrinsicContentSize.height
        self.contentView.addAutoLayoutSubview(self.button)
    }
}

class UtteranceButton: CellPrimaryButton {
    let utteranceText: String
    let performUtterance: (String) -> Void

    init(buttonTitle titleLabel: String,
         maxWidth: CGFloat,
         utteranceText: String,
         onPress: @escaping (String) -> Void) {

        self.utteranceText = utteranceText
        self.performUtterance = onPress

        super.init(buttonTitle: titleLabel, maxWidth: maxWidth)
    }
}

Try this way of calling an action. 尝试使用这种方式来调用动作。

UIApplication.shared.sendAction(#selector(didTapUtteranceButton), to: self, from: nil, for: nil)

instead of this one: 而不是这个:

utteranceButton.button.addTarget(self, #selector(didTapUtteranceButton), for: .touchUpInside)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM