やりたいことがよくわからないのですが ForEach
から渡される値を利用してはいかがでしょうか。
VStack {
ForEach(0 ..< 5) { i in
Text("\(i + 1)")
}
ForEach(0 ..< 5) { i in
Text("\(i + 1)")
}
}
1Like
swiftUIを勉強中の者です。
ForEach文でTextビューを並べる際に、並べた回数をカウントしておきたかったため、以下に載せるサンプルコードのようなカウントアップ用の関数を作成しました。
以下コードで期待していた動き方は、
①”処理A”で、counter関数により1〜5までカウント
↓
②counter関数の返り値である変数cntを一旦初期化
↓
③”処理B”でも、counter関数により1〜5までカウント
でした。
しかし、処理Bでは処理Aでカウントしていた数の続きからカウントされて6〜10とカウントされてしまいます。
これは、なぜでしょうか。
ご存知の方、ご教授をお願いいたします。
//Xcodeのバージョン Version 12.3 (12C33)
//Swiftのバージョン Apple Swift version 5.3.2
import SwiftUI
//カウントアップ用の関数
var mode: Int = 0
var cnt: Int = 0
func counter(mode: Int) -> Int {//
switch mode {
case 0:
cnt += 0
case 1:
cnt += 1
case 2:
cnt = 0
default:
print("error")
}
return cnt
}
struct ContentView: View {
var body: some View {
VStack {
//■処理A■
//Textビューを1枚ずつ5回並べ、並べる度にcounter関数を呼び出して返り値の変数cntを表示
//(1〜5と表示されたテキストボックスが並びます)
HStack(spacing: 10) {
ForEach(0..<5) { i in
Text("\(counter(mode: 1))")//
.frame(width: 30, height: 30)
.border(Color.black, width: 1)
}
}
//■カウンター初期化■
//数字のカウントに用いたcounter関数の返り値を0に戻したいために、このようにしています。
//他に良い初期化の方法があればアドバイスいただけると幸いです。
Text("\(counter(mode: 0))")
.frame(width: 30, height: 30)
.foregroundColor(.black)
Text("\(cnt)")
//■処理B■
//Textビューを1枚ずつ5回並べ、並べる度にcounter関数を呼び出して返り値の変数cntを表示
//(6〜10と表示されたテキストボックスが並びます)
//変数cntを0に戻しているので、処理Aと同様に1〜5と表示させたいのですが、
//処理Aの続きからカウントされてしまいます。 なぜでしょうか?
HStack(spacing: 10) {
ForEach(0..<5) { i in
Text("\(counter(mode: 1))")//
.frame(width: 30, height: 30)
.border(Color.black, width: 1)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
やりたいことがよくわからないのですが ForEach
から渡される値を利用してはいかがでしょうか。
VStack {
ForEach(0 ..< 5) { i in
Text("\(i + 1)")
}
ForEach(0 ..< 5) { i in
Text("\(i + 1)")
}
}
@_mitty
Questioner@_mitty
Questioner@_mitty
Questionerシンタックスハイライトが効かないので新しくコメントします。
その例でいうと、日付が何日から何日までかを計算するだけでなく、その日付の一覧をつくるところまでやってください。
// 表示したい日付の一覧
let dates: [Date] = ...
// 表示に使うデータ
let rows: [[Date]] = /* 日付の一覧を変換して6x7の配列にする */
// UIに表示する
var body: some View {
VStack {
ForEach(rows, id: \.self) { (columns: [Date]) in
HStack {
ForEach(columns, id: \.self) { (date: Date) in
// 適当に表示する
Text("\(DateFormatter.localizedString(from: date, dateStyle: .short, timeStyle: .none))")
}
}
}
}
}
特定の日だけ見た目を変えたいときは、データ構造の変更などが考えられそうですね。
struct Item: Hashable {
let date: Date
let isSpecial: Bool
func hash(into hasher: inout Hasher) {
hasher.combine(date)
}
}
let items: [Item] = ...
let rows: [[Item]] = ...
var body: some View {
VStack {
ForEach(rows, id: \.self) { (columns: [Item]) in
HStack {
ForEach(columns, id: \.self) { (item: Item) in
let text = DateFormatter.localizedString(from: item.date, dateStyle: .short, timeStyle: .none
if item.isSpecial {
// 特別な日は赤くしよう
Text("\(text)").foregroundColor(.red)
} else {
Text("\(text)")
}
}
}
}
}
}
表示したいデータを用意する処理と、実際にそれを表示する処理は分けて考えるようにしてください。
追記:rowとcolumnが逆だったので修正
@_mitty
Questioner@_mitty
Questioner@_mitty
Questioner