SwiftUI का उपयोग कर - चर गिनती के भीतर ForEach

0

सवाल

मैं एक देखने के माध्यम से बनाई गई एक ForEach पाश की जरूरत है, जो लेने के लिए एक चर गिनती के भीतर ForEach ही यानी मैं app की जरूरत के लिए प्रतिक्रिया करने के लिए एक गतिशील गिनती और यूआई बदलें 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 देखें.

हालांकि, whilst 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

ठीक है तो मैं लग रहे करने के लिए एक हल मिल गया है - मैं क्या हूँ, अपने ऊपर भरोसा रखनेवाला है कि ForEach एक सीमा से युक्त नहीं करता है गतिशील रूप से अद्यतन कि एक ही रास्ते में ForEach युक्त वस्तुओं की एक सरणी है.

तो बजाय:

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

आदि.

मैं इसे बदल करने के लिए:

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

इस तरह से मैं अभी भी पुनरावृति आवश्यक समय की संख्या लेकिन ForEach अद्यतन गतिशील रूप से सही संख्या के साथ वस्तुओं की सरणी में

2021-11-23 23:51:48

की तरह लग रहा है दस्तावेज क्या कहते हैं के रूप में ज्यादा: "उदाहरण केवल पढ़ता है, प्रारंभिक मूल्य के लिए प्रदान की जाती डेटा और नहीं की जरूरत की पहचान करने के लिए विचारों के पार अद्यतन. गणना करने के लिए पर विचारों की मांग पर एक गतिशील रेंज, का उपयोग ForEach/init(_:आईडी:सामग्री:)."
Charles A.

अन्य भाषाओं में

यह पृष्ठ अन्य भाषाओं में है

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................