#swift #swiftui
#swift #swiftui
Вопрос:
У меня есть следующие структуры, определенные в соответствии с примером SwiftUI в Apple.
struct Cat: Hashable, Codable, Identifiable {
let id: Int
let name: String
let audio: [Int]? // list of audio of cat sound
}
struct CatAudio: Hashable, Codable, Identifiable {
let id: Int
let filename: String
}
Затем я хотел бы получить доступ к аудио, а затем передать его в представлении.
У меня есть данные json, подобные этому:
[
{
"id": 55,
"name": "meow",
"audio": [6,5]
},
{
"id": 3,
"name": "meowmeow",
"audio": [2]
}
]
audioData.json
[
{
"id": 5,
"filename": "5.wav"
},
{
"id": 2,
"filename": "2.wav"
},
{
"id": 6,
"filename": "6.wav"
}
]
Файлы json успешно загружены.
@Published var cats: [Cat] = load("CatData.json")
@Published var catAudios: [CatAudio] = load("CatAudio.json")
Затем я попытался получить аудиообъект из данных моей модели среды:
@EnvironmentObject var modelData: ModelData
и затем я хочу получить соответствующий аудиообъект cat. но мне не удалось этого сделать, поскольку я не знаю, как использовать «Идентификатор» для его получения.
Пример:
Предположим, что я получил объект cat из своей модели:
let cat = modelData.cats[0]
Затем я хочу получить его аудиоданные в соответствии с идентификатором, хранящимся в его списке аудиозаписей
let catAudio = modelData.catAudios[cat.audio[0]!] // exception here
Я обнаружил, что это связано с тем, что порядок массива может не соответствовать «Идентификатору». Я хочу использовать «Идентификатор» вместо порядка массива, чтобы получить элемент.
Как я могу это сделать?
========
Я попытался написать функцию для получения списка CatAudio кота. Я также сделал аудио необязательным.
func getAudio(cat: Cat) -> [CatAudio] {
return cat.audio.compactMap{id in catAudio.filter { $0.id==id } }
}
Но он жалуется и говорит, что не может преобразовать значение типа [CatAudio] в тип результата закрытия ‘CatAudio’
Я запутался с этим.
Ответ №1:
Вам необходимо использовать функции высокого порядка для сопоставления значений идентификаторов в audio
массиве с элементами в массиве CatAudio
Предполагая, что 2 массива и выбранный объект Cat
var cats: [Cat] = ...
var catAudios: [CatAudio] = ...
let cat = cats[0]
Чтобы выбрать один звук для одного идентификатора
if let firstId = cat.audio?.first {
let audio = catAudios.first { $0.id == firstId}
}
Чтобы получить массив всех CatAudio для cat
объекта
if let array = cat.audio {
let values = array.compactMap { id in catAudios.filter { $0.id == id }}
}
Код был бы проще, если audio
бы массив не был необязательным, есть ли причина для его объявления необязательным?
Комментарии:
1. У некоторых cat нет записи голоса, поэтому необязательно. Тем не менее, я могу изменить его на массив размером 0, это нормально. Как код может быть проще, если это необязательно ?!
2. Эффективен ли приведенный выше код, если у меня много кошек? Представьте, что это итератор, который перебирает все объекты в списке и проверяет один за другим?
3. @user6539552 С необязательным массивом вы можете пропустить некоторые
if let...
, которые могут сделать код короче и понятнее, но это не обязательно. Если у вас много объектов Cat, было бы неплохо превратить массив CatAudio в словарь с идентификатором в качестве ключа для более быстрого поиска.4. Я новичок в разработке. Я только следую руководству в Apple, оно загружает данные в список из Json. Вы имеете в виду, что я должен изменить код в этот момент, не используя array для хранения данных Json? В чем будет разница, если я использую dict для хранения элементов?
5. я попытался написать функцию для получения списка объектов CatAudio с помощью фильтра, но, похоже, это не работает.. Я должен сделать CatAudio необязательным. (Я отредактировал свой вопрос, чтобы включить код)