Я работаю над личным приложением и хочу обновить код. В настоящее время я использую внешнюю библиотеку кокоса под названием «Диаграммы» для создания диаграмм в своем приложении (которое находится на Swift). Тем не менее, я мог заметить, что могу реализовать встроенную библиотеку «Диаграммы» SwiftUI и реализовать ее в своем коде, но я еще не владею SwiftUI. Для этого я использую разные источники (например, это руководство на YouTube и другое руководство). Тем не менее, я хотел бы показать 3 значения в месяц, как показано на изображении под названием «01_3BarsPerMonth» (которое было создано с использованием библиотеки Cocopod «Диаграммы» в исходном проекте), но самое близкое, чего я достиг, это тот, который показан во второй ссылке, которую я вам предоставил (см. изображение «02_CurrentResult»), который в настоящее время создан с использованием собственной библиотеки «Диаграммы» SwiftUI. Я искал другие примеры, но у них есть более (и сложный) код, который на данный момент мне не нужен, и я верю, что с тем, что у меня есть на данный момент, я мог бы получить желаемые результаты.
В тестовом коде, который я сейчас использую (небольшое практическое приложение для ознакомления с библиотекой «Диаграммы» SwiftUI), это мой класс ViewController:
import SwiftUI
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupView()
}
// MARK: - Setup view
private func setupView() {
view.backgroundColor = .lightGray
let horizontalConstraint: CGFloat = 10
//let controller = UIHostingController(rootView: SavingsHistory())
let controller = UIHostingController(rootView: OrdersHistory())
guard let savingsView = controller.view else { return }
savingsView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(savingsView)
NSLayoutConstraint.activate([
savingsView.topAnchor.constraint(equalTo: view.topAnchor),
savingsView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
savingsView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor, constant: horizontalConstraint),
savingsView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor, constant: -horizontalConstraint)
])
}
}
И это код моей структуры:
import SwiftUI
import Charts
struct Order: Identifiable {
var id: String = UUID().uuidString
var amount: Int
var day: Int
}
struct OrdersHistory: View {
var ordersWeekOne: [Order] = [
Order(amount: 10, day: 1),
Order(amount: 7, day: 2),
Order(amount: 4, day: 3),
Order(amount: 13, day: 4),
Order(amount: 19, day: 5),
Order(amount: 6, day: 6),
Order(amount: 16, day: 7)
]
var ordersWeekTwo: [Order] = [
Order(amount: 20, day: 1),
Order(amount: 14, day: 2),
Order(amount: 8, day: 3),
Order(amount: 26, day: 4),
Order(amount: 27, day: 5),
Order(amount: 12, day: 6),
Order(amount: 32, day: 7)
]
var ordersWeekThree: [Order] = [
Order(amount: 5, day: 1),
Order(amount: 3, day: 2),
Order(amount: 2, day: 3),
Order(amount: 7, day: 4),
Order(amount: 10, day: 5),
Order(amount: 3, day: 6),
Order(amount: 8, day: 7)
]
var body: some View {
Chart {
ForEach(ordersWeekOne, id: \.id) { order in
LineMark(
x: PlottableValue.value("Week 1", order.day),
y: PlottableValue.value("Orders 1", order.amount),
series: .value("Week", "One")
)
.foregroundStyle(Color.red)
}
ForEach(ordersWeekTwo, id: \.id) { order in
LineMark(
x: PlottableValue.value("Week 2", order.day),
y: PlottableValue.value("Orders 2", order.amount)
,
series: .value("Week", "Two")
)
.foregroundStyle(Color.green)
}
ForEach(ordersWeekThree, id: \.id) { order in
LineMark(
x: PlottableValue.value("Week 3", order.day),
y: PlottableValue.value("Orders 3", order.amount)
,
series: .value("Week", "Three")
)
.foregroundStyle(Color.black)
}
}
}
}
Я пытался изменить приведенный выше пример, но всегда получаю сообщение об ошибке, например «[OrdersHistory] должно соответствовать Identifying» или что-то в этом роде, когда я пытаюсь создать объект типа [[OrdersHistory]].
Что я могу изменить, чтобы получить результат, как на первом изображении (например, 3 значения для января).
Я ценю ваш отзыв. С уважением.
Привет, уборщик. Спасибо за вопрос. Используя библиотеку диаграмм SwiftUI, я хочу создать гистограмму, похожую на изображение «Облученность на плоской поверхности», которым я поделился в своем первом вопросе. Итак, в моем практическом коде у меня есть 3 массива с данными (ordersWeekOne,ordersWeekTwo иorderWeekThree), и я хотел бы создать диаграмму, используя эти данные, и гистограмма должна выглядеть как упомянутое ранее изображение. Если я изменю линейную диаграмму на гистограмму, я получу сложную гистограмму, а это не то, что мне нужно. Надеюсь, я прояснил ваше замешательство. С уважением.
Я понимаю. Кажется, вам просто нужно передать .unstacked
параметру stacking:
BarMark.init.
Привет, уборщик. Я уже пробовал, но он показывает сложенную гистограмму, где красная полоса (соответствующая массиву «ordersWeekOne») «исчезает». Еще раз спасибо за ваш ответ.
Я бы начал с рефакторинга вашего типа Order
, включив в него номер недели.
struct Order: Identifiable {
var id: String = UUID().uuidString
var week: Int
var amount: Int
var day: Int
}
Тогда вы можете использовать один массив в качестве источника данных.
var orders: [Order] = [
Order(week: 1, amount: 10, day: 1),
Order(week: 1, amount: 7, day: 2),
...
Order(week: 3, amount: 3, day: 6),
Order(week: 3, amount: 8, day: 7)
]
Тогда нам нужно использовать строки для наших меток/групп вместо Int
.
extension Order {
var weekLabel: String {
"\(week)"
}
var dayLabel: String {
Calendar.current.weekdaySymbols[day-1]
}
}
И теперь мы можем использовать эти метки и массив для диаграммы.
Chart {
ForEach(orders) { order in
BarMark(
x: .value("Day", order.dayLabel),
y: .value("Amount", order.amount)
)
.foregroundStyle(by: .value("Week", order.weekLabel))
.position(by: .value("Week", order.weekLabel))
}
}
Если вы хотите работать с тремя разными массивами, вы можете объединить их в массив массивов.
let ordersWeek: [[Order]] = [
[
Order(amount: 10, day: 1),
Order(amount: 7, day: 2),
//...
], [
Order(amount: 20, day: 1),
Order(amount: 14, day: 2),
//...
], [
Order(amount: 5, day: 1),
Order(amount: 3, day: 2),
//...
]
]
А затем используйте укладку, как предложено @Sweeper.
Chart {
ForEach(ordersWeek.indices, id: \.self) { index in
ForEach(ordersWeek[index]) { order in
BarMark(
x: .value("Day", order.dayLabel),
y: .value("Amount", order.amount),
stacking: MarkStackingMethod.standard)
.foregroundStyle(by: .value("Week", "\(index + 1)"))
.position(by: .value("Week", "\(index)"))
}
}
}
Альтернативный способ создания массива массивов из исходных свойств массива — использовать вычисляемое свойство:
var ordersWeek: [[Order]] {
[ordersWeekOne, ordersWeekTwo, ordersWeekThree]
}
Привет Йоаким. Спасибо за ваш возможный ответ.
Это действительно один из способов получить желаемый результат. Однако я также хотел бы знать, как это сделать, используя три массива, которые я изначально опубликовал в вопросе. Я знаю, что мне нужно будет использовать вложенный ForEach (как в более сложных примерах, которые я видел и упоминал в исходном вопросе ранее). Знаете, чтобы получить «больше оружия», используя общие знания от тех, кто знает больше, как в вашем случае. Я более опытен в использовании UIKit, SwiftUI не моя опора, но сейчас я его изучаю. Еще раз спасибо за любую возможную помощь
@J_A_F_Casillas Ответ дополнен альтернативным решением
Спасибо @Joakim и Sweepers за сотрудничество. Я внес некоторые небольшие изменения (например, сделал «day: String» вместо «day: Int» в структуре «struct Order: Identifying»), но с помощью кода, который вы любезно предоставили, я смог добиться того, чего хотел. Большое спасибо :)
И последний вопрос: как я могу изменить/настроить цвет диаграмм? Я попробовал использовать .chartForegroundStyleScale([ "Week 1": .green, "Week 2": .red, "Week 3": .blue ]) после строки Chart {, но это не работает. Еще раз спасибо.
Изучите модификатор ChartForegroundStyleScale для Chart.
@J_A_F_Casillas Не забудьте принять ответ, поскольку он помог вам достичь того, чего вы хотели.
Это очень сбивает с толку. Ваш исходный код создает гистограмму, а код SwiftUI создает линейную диаграмму? Для линейного графика результат мне кажется правильным. Вам нужен линейный график или гистограмма?