SwiftUI-โดยใช้ตัวแปรนับภายใน ForEach

0

คำถาม

ฉันมีมุมมองสร้างผ่าน ForEach วซึ่งต้องการจะใช้ตัวแปรนับภายใน ForEach ตัวมันเอง i.e. ฉันต้องการโปรแกรมีปฏิกิริยาตอบโต้เพื่อเป็นแมสซีฟไดนามินับแล้วเปลี่ยนส่วนติดต่อผู้ใช้ขอ accoridngly.

นี่คือมุมมองผมพยายามที่จะแก้ไข:

struct AnimatedTabSelector: View {
    let buttonDimensions: CGFloat
    @ObservedObject var tabBarViewModel: TabBarViewModel
    
    var body: some View {
        HStack {
            Spacer().frame(maxWidth: .infinity).frame(height: 20)
                .background(Color.red)
            
            ForEach(1..<tabBarViewModel.activeFormIndex + 1) { _ in
                Spacer().frame(maxWidth: buttonDimensions).frame(height: 20)
                    .background(Color.blue)
                Spacer().frame(maxWidth: .infinity).frame(height: 20)
                    .background(Color.green)
            }
            
            Circle().frame(
                width: buttonDimensions,
                height: buttonDimensions)
                .foregroundColor(
                    tabBarViewModel.activeForm.loginFormViewModel.colorScheme
                )
            
            ForEach(1..<tabBarViewModel.loginForms.count - tabBarViewModel.activeFormIndex) { _ in
                Spacer().frame(maxWidth: .infinity).frame(height: 20)
                    .background(Color.red)
                Spacer().frame(maxWidth: buttonDimensions).frame(height: 20)
                    .background(Color.blue)
            }
            
            Spacer().frame(maxWidth: .infinity).frame(height: 20)
                .background(Color.gray)
        }
    }
}

และ viewModel ฉันเป็นนัก:

class TabBarViewModel: ObservableObject, TabBarCompatible {
    var loginForms: [LoginForm]
    @Published var activeForm: LoginForm
    @Published var activeFormIndex = 0
    private var cancellables = Set<AnyCancellable>()
    
    init(loginForms: [LoginForm]) {
        self.loginForms = loginForms
        self.activeForm = loginForms[0] /// First form is always active to begin
        setUpPublisher()
    }
    
    func setUpPublisher() {
        for i in 0..<loginForms.count {
            loginForms[i].loginFormViewModel.$isActive.sink { isActive in
                if isActive {
                    self.activeForm = self.loginForms[i]
                    self.activeFormIndex = i
                }
            }
            .store(in: &cancellables)
        }
    }
}

และสุดท้ายที่ loginFormViewModel:

class LoginFormViewModel: ObservableObject {
    @Published var isActive: Bool
    
    let name: String
    let icon: Image
    let colorScheme: Color
    
    init(isActive: Bool = false, name: String, icon: Image, colorScheme: Color) {
        self.isActive = isActive
        self.name = name
        self.icon = icon
        self.colorScheme = colorScheme
    }
}

พื้นฐานแล้วเป็นปุ่มบล็อกอินรูปแบบตัวเองตั้งค่าของมัน viewModel น isActive ทรัพย์สินเพื่อนเรื่องจริง เราฟังเรื่องนี้อยู่ใน TabBarViewModel และตั้ง activeFormIndex กว่านี้ละกัน นี่ดัชนีคืนนั้นเคยอยู่ใน ForEach เรื่อยๆ โดยพื้นฐานขึ้นอยู่กับคนดัชนีที่เลือกไว้ฉันต้องการสร้างมากกว่าหรือน้อยกว่า spacers ใน AnimatedTabSelector องมุมมอง

อย่างไรก็ตามระหว่างที่ค activeIndex ตัวแปรก็คือการเป็นตัวปรับปรุงล่าสุดแล้ที่ ForEach ดูเหมือนจะไม่ได้เกิดปฏิกิริยา

ปรับปรุง:

ที่ AnimatedTabSelector คือประกาศเป็นส่วนหนึ่งของที่ผ่านมุมมอง:

struct TabIconsView: View {
    
    struct Constants {
        static let buttonDimensions: CGFloat = 50
        static let buttonIconSize: CGFloat = 25
        static let activeButtonColot = Color.white
        static let disabledButtonColor = Color.init(white: 0.8)
        
        struct Animation {
            static let stiffness: CGFloat = 330
            static let damping: CGFloat = 22
            static let velocity: CGFloat = 7
        }
    }
    
    @ObservedObject var tabBarViewModel: TabBarViewModel
    
    var body: some View {
        ZStack {
            AnimatedTabSelector(
                buttonDimensions: Constants.buttonDimensions,
                tabBarViewModel: tabBarViewModel)
            
            HStack {
                Spacer()
                
                ForEach(tabBarViewModel.loginForms) { loginForm in
                    Button(action: {
                        loginForm.loginFormViewModel.isActive = true
                    }) {
                        loginForm.loginFormViewModel.icon
                            .font(.system(size: Constants.buttonIconSize))
                            .foregroundColor(
                                tabBarViewModel.activeForm.id == loginForm.id ? Constants.activeButtonColot : Constants.disabledButtonColor
                            )
                    }
                    .frame(width: Constants.buttonDimensions, height: Constants.buttonDimensions)
                    Spacer()
                }
            }
        }
        .animation(Animation.interpolatingSpring(
            stiffness: Constants.Animation.stiffness,
            damping: Constants.Animation.damping,
            initialVelocity: Constants.Animation.velocity)
        )
    }
}

ปรับปรุง:

ฉันพยายามทางอื่นโดยการเพิ่มอีกตีพิมพ์ออกไป AnimatedTabSelector งตัวเองไปตรวจสอบว่าคุณค่าเป็นจริงถูกปรับปรุงกว่านี้ละกัน ดังนั้นในตอนจบของ HStack ในมุมมองฉันถูกเพิ่ม:

.onAppear {
            tabBarViewModel.$activeFormIndex.sink { index in
                self.preCircleSpacers = index + 1
                self.postCircleSpacers = tabBarViewModel.loginForms.count - index
            }
            .store(in: &cancellables)
        }

และแน่นอนฉันเพิ่มให้มีการติดตามตัวแปรนี้ในมุมมอง:

@State var preCircleSpacers = 1
@State var postCircleSpacers = 6
@State var cancellables = Set<AnyCancellable>()

แล้วในตอ ForEach บางอย่างฉันเปลี่ยนแปลงเป็น:

ForEach(1..<preCircleSpacers)

แล้ว

ForEach(1..<postCircleSpacers)

ตามลำดับ

ฉันเพิ่มทำลายประเด็นที่ใหม่สำนักพิมพ์ปล่อยให้เธอได้หายใจอยู่อีกและมันแน่อยู่แล้วเข้าชุดเหมาะเหม็งการปรับที่คาดหวังลักปลายๆด้วยนะ แต่มุมมองยังคงล้มเหลวเพื่อจะได้ไตร่ตรองการเปลี่ยนค่า

combine swift swiftui
2021-11-23 22:03:33
1

คำตอบที่ดีที่สุด

0

โอเคดังนั้นฉันดูเหมือนจะเจอวิธีแก้ปัญหา-อะไรฉัน presuming นั่นคือ ForEach บรรจุเป็นช่วงไม่ปรับปรุง dynamically ในแบบเดียวกับที่นั่น ForEach บรรจุข้อาเรย์ของวัตถุน

ดังนั้นมากกว่า:

ForEach(0..<tabBarViewModel.loginForms.count)

เป็นต้น

ฉันเปลี่ยนมันไปยัง:

ForEach(tabBarViewModel.loginForms.prefix(tabBarViewModel.activeFormIndex))

ทางนี้ฉันยังคง iterate ที่ต้องการจำนวนครั้งแต่ ForEach ปรับปรุง dynamically กับที่ถูกต้องเบอร์ของรายการต่างๆในตารางคู่ลำดับ

2021-11-23 23:51:48

ดูเหมือนว่า เอกสารที่ ยังพูดอย่าง:"ปกตัวอย่างเดียวที่ได้ยินจุดเริ่มต้นค่าของที่เตรียมไว้ให้ด้านล่างข้อมูลและไม่ต้องการที่จะระบุตัวมุมมองข้ามองรายงานแล้ว ต้องสะทกสะทานเลยละสิมุมมองการทำงานอัตโนมัติเมื่อต้องเป็นปรับอัตโนมัติช่วงใช้ ForEach/init(_:ชื่อ:เนื้อหาภายใน:)."
Charles A.

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................