Как я могу вызвать функцию со словарем? - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь создать Dictionary для вызова некоторых функций.

Мой массив принимает ключ Int, строку и функцию, например:

let list_weapons: [Int: [Any]]  = [1: ["Sword", attack_sword],
                                   2: ["Magic wand", heal_magic_wand],
                                   3: ["Hammer", attack_hammer],
                                   4: ["Axe", attack_axe]]

Эти функции принимаютClass в качестве параметра, например:

func attack_sword(character: Character)

Я пытаюсь вызвать мою функцию таким образом, но она не работает.

list_weapons[1]![1](character: Character) 

Невозможно вызвать значениене функционального типа 'Any'

Если у вас есть идеи или посоветовать мне другой контейнер

Спасибо

Ответы [ 4 ]

0 голосов
/ 18 сентября 2018

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

// Here you can specify all common thing about your weapons
protocol Weapon: class {
    var name: String { get }
    func attack(character: Character)
}

// Each weapon has its own class which can contain eveything you need
class Sword: Weapon { }
class MagicWand: Weapon { }
class Hammer: Weapon { }
class Axe: Weapon { }

// That's how you can store you weapons list
// You can use a dictionary if you like
let weaponsArray: [Weapon]  = [Sword(),
                               MagicWand(),
                               Hammer(),
                               Axe()]

// And that's how you can use them
weaponsArray[0].attack(character: character)
0 голосов
/ 18 сентября 2018

Использование массива Any для хранения строки и замыкания (функции) с определенной сигнатурой - плохой выбор.Было бы лучше объявить struct с двумя свойствами правильного типа.Затем сохраните эти структуры в своем словаре.

struct Action {
    let name: String
    let function: (Character) -> ()
}

let list_weapons: [Int: Action] = [
    1: Action(name: "Sword", function: attack_sword),
    // and the rest
]

list_weapons[1]!.function(someCharacter)
0 голосов
/ 18 сентября 2018

Вы можете привести элемент к типу функции:

if let attack = list_weapons[1]![1] as? ((Character) -> Void) {
    attack(...)
} else {
    print("Cannot attack")
}

Но вам лучше переделать модель данных.Использование словарей может очень быстро запутать.Вот один из способов сделать это:

protocol Weapon {
    var name: String { get }
    func attack(character: Character)
}

struct Sword: Weapon {
    let name = "Sword"
    func attack(character: Character) { ... }
}

struct MagicWand: Weapon {
    let name = "Magic Wand"
    func attack(character: Character) { ... }
}

struct Hammer: Weapon {
    let name = "Hammer"
    func attack(character: Character) { ... }
}

struct Axe: Weapon {
    let name = "Axe"
    func attack(character: Character) { ... }
}

let weapons: [Weapon] = [Sword(), MagicWand(), Hammer(), Axe()]
weapons[1].attack(character: ...)

Вы расширяете каждое оружие различными уронами, уникальными особенностями, уровнями и т. Д.

0 голосов
/ 18 сентября 2018

Вы должны cast Любой до Функции перед ее использованием.

let f = (list_weapons[1]![1] as! (Character) -> Void)
f("a") //it will invoke attack_sword("a")

И без временной переменной,

(list_weapons[1]![1] as! (Character) -> Void)("a")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...