Как я могу правильно изменить действие кнопки IBAction, используя быстрый оператор?

Я поднял этот вопрос в одном из своих других вопросов, но я работаю над текстовой приключенческой игрой, разработанной для IOS.

Одна из вещей, над которыми я работаю, — дать кнопке несколько различных функций при определенных обстоятельствах. Я читал в нескольких других сообщениях, что я могу добиться этого, используя быстрые операторы, и мне удалось несколько изменить действие, однако это не правильное действие.

Как показано ниже, большая часть моей истории, а также те варианты, которые даны игроку, хранятся в структуре и могут переключаться с помощью метода PickStory.

func mainStory()
{
    Storys =
        [Story(Story: "You are walking along a dirt path and come to a cross roads. You see a small shack just off the trail. What do you want to do?", Action: "Heal", North: true, South: true, East: false, West: false, storyProg: true, resultN: "You walk north and see a gate in the distance.", resultS: "Their is nothing to turn back for.", resultE: "", resultW: ""),

         Story(Story: "You see a small gate at the end of the dirt path, and their is a gaurd standing infront of the gate.", Action: "Approach", North: true, South: true, East: true, West: true, storyProg: false, resultN: "", resultS: "", resultE: "", resultW: ""),

         Story(Story: "You see a small well in the middle of town.", Action: "Attack", North: true, South: true, East: true, West: true, storyProg: false, resultN: "", resultS: "", resultE: "", resultW: "")]


    PickStory()
}

func PickStory()
{
    if Storys.count > 0
    {
        storyNum = 0
        storyLabel.text = Storys[storyNum].Story
        actionButton.setTitle(Storys[storyNum].Action, for: UIControl.State.normal)

        adjustButtons(North: Storys[storyNum].North,
                      South: Storys[storyNum].South,
                      East: Storys[storyNum].East,
                      West: Storys[storyNum].West)

        Storys.remove(at: storyNum)
    }
    else
    {
        NSLog("Done!")
    }
}

Теперь, когда текст кнопки «Действие» устанавливается в методе PickStory, фактические действия изменяются в методе фактической кнопки, который следует через несколько строк после него (обратите внимание, что операторы печати являются лишь временными заполнителями для методов, которые будут размещены). потом).

@IBAction func actionButton(_ sender: Any)
{
    switch Storys[storyNum].Action
    {
        case "Attack":
            print("Attacking")
            break
        case "Heal":
            print("Healing")
            break
        case "Approach":
            print("Approaching")
            break
    default:
        break
    }
}

Подводя итог проблеме, текст изменится на правильное действие, но фактическое действие не изменится.

Мое первоначальное предположение заключалось в том, что, поскольку actionButton появляется немного позже, после метода PickStory, он будет читать следующую историю после удаления индекса. Однако я не могу добиться прогресса в истории, не удаляя индексы.


person Jacob Mehnert    schedule 28.04.2019    source источник
comment
storyNum объявлен глобально? Кроме того, вы удаляете историю по индексу storyNum, так что, возможно, проблема в том, что ее не существует, когда вы проверяете ее в операторе switch.   -  person Chris    schedule 28.04.2019
comment
@ Крис, да, но больше нигде в коде это не меняется. Он просто используется, чтобы помочь переключать операторы. Также я считаю, что это может быть причиной проблемы.   -  person Jacob Mehnert    schedule 28.04.2019
comment
Я не совсем понимаю, что делает adjustButtons(). Одним из решений может быть создание подкласса UIButton и добавление свойства storyAction, к которому затем можно получить доступ в операторе switch с помощью sender.storyAction.   -  person Chris    schedule 28.04.2019
comment
AdjustButtons() на самом деле является просто методом, который позволяет включать/отключать различные кнопки в определенных обстоятельствах. Поэтому, если игрок находится в коридоре, он может двигаться только в двух направлениях.   -  person Jacob Mehnert    schedule 28.04.2019


Ответы (1)


Вы не можете отправлять параметры через действие селектора, но вы можете создать подкласс UIButton, чтобы добавить пользовательское свойство, которое может быть любым.

import UIKit

class CustomButton: UIButton {
    var storyAction: String

    override init(frame: CGRect) {
        self.storyAction = ""
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        self.storyAction = ""
        super.init(coder: aDecoder)
    }
}

Вы можете установить это свойство при установке заголовка:

let action = Storys[storyNum].action // Customary to use lower case for instance properties and upper case for classes
actionButton.setTitle(action, for: UIControl.State.normal)
actionButton.storyAction = action

Вы можете проверить это в операторе switch.

@IBAction func actionButton(_ sender: CustomButton)
{
    switch sender.storyAction
    {
        case "Attack":
            print("Attacking")
            break
        case "Heal":
            print("Healing")
            break
        case "Approach":
            print("Approaching")
            break
    default:
        break
    }
}

Обратите внимание, что я назвал свойство storyAction, чтобы не конфликтовать с ранее существовавшим свойством кнопки action.


Возможно, безопаснее использовать enum для всех типов storyAction вместо строк. Это облегчит проверку отсутствия орфографических ошибок, вызывающих проблемы!

enum StoryAction {
    case attack
    case heal
    case approach
}

Это может быть расширено столько, сколько вам нужно. Это легко проверить в операторе switch с помощью case .attack и т. д.

person Chris    schedule 28.04.2019
comment
Я обновил ответ, так как отправитель селектора IBAction должен иметь тип CustomButton вместо Any, так что приведение не требуется, и компилятор знает, что он будет иметь свойство storyAction. - person Chris; 28.04.2019