ट्यूटोरियल से https://developer.apple.com/tutorials/swiftui/handling -उपयोगकर्ता-इनपुट, इसमें "isFavourite" इंगित करने के लिए स्टार है।

मैंने स्टार को एक बटन में बदल दिया है, यदि उपयोगकर्ता ने उस पर टैप किया है, और फिर यह isFavourite मान को टॉगल करेगा।

struct LandmarkRow: View {

    @State var landmark: Landmark
    @State var isChecked: Bool = false

    var body: some View {
        HStack {
            landmark.image
                .resizable()
                .frame(width: 50, height: 50)
            Text(landmark.name)

            Spacer()

            Button(action: {
                self.isChecked.toggle()
                landmark.isFavourite.toggle() // tried to modify the landmark value
            }, label: {
                if self.isChecked {
                    Image(systemName: "checkmark.square.fill")
                        .imageScale(.large)
                } else {
                    Image(systemName: "square")
                        .imageScale(.large)
                }
            })
        }
    }
}

हालाँकि, मुझे यहाँ एक समस्या मिली।

लैंडमार्कलिस्ट व्यू पर वापस, मैं यह गिनना चाहता हूं कि कितने लैंडमार्क चुने गए हैं। हालांकि, जब मैं स्थलों के माध्यम से लूप के लिए लूप का उपयोग करता हूं, तो मैंने पाया कि isFavourite मान संशोधित नहीं है।

struct LandmarkList: View {
    var body: some View {
        NavigationView {
            VStack {

            Text("\(getCount(landmarks)") // fail here, it shows 0 forever
            List(landmarks) { landmark in
                NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                    LandmarkRow(landmark: landmark)
                }
            }
            }
            .navigationTitle("Landmarks")
        }
    }
}

मेरे पास लैंडमार्कलिस्ट में एक फ़ंक्शन getCount है:

func getCount(landmarks: [Landmark]) -> Int {
    var count: Int = 0
    for landmark in landmarks {
        if landmark.isFavourite {
           count += 1
        }
    }
    return count
}

क्या यह @State की वजह से है? या यहाँ क्या गलत हुआ है?

0
user6539552 20 जिंदा 2021, 18:57
1
आपको अपने लैंडमार्करो पर एक बाइंडिंग पास करने की आवश्यकता है क्योंकि आप केवल पंक्ति में पसंदीदा मान को अपडेट कर रहे हैं, और वास्तविक डेटा में कभी नहीं जो पंक्ति की आपूर्ति करता है
 – 
Andrew
20 जिंदा 2021, 19:23
एक अच्छी युक्ति हमेशा @State गुणों को private के रूप में घोषित करना है। आपको landmark को @State के रूप में LandmarkRow दृश्य के बाहर से एक्सेस नहीं करना चाहिए।
 – 
pawello2222
20 जिंदा 2021, 19:24
क्या यह आपके प्रश्न का उत्तर देता है stackoverflow.com/a/59316596/12299030?
 – 
Asperi
20 जिंदा 2021, 19:46

1 उत्तर

सबसे बढ़िया उत्तर

जैसा कि मैंने ऊपर अपनी टिप्पणी में कहा था कि आप वास्तव में स्थलों की वैश्विक स्थिति को अपडेट नहीं कर रहे हैं, केवल वह राज्य जो पंक्ति में मौजूद है, आपको बाध्यकारी का उपयोग करने या ModelData में मूल्य तक पहुंचने की आवश्यकता होगी आयोजित पर्यावरण में।

यदि आप LandmarkDetail पृष्ठ को देखें तो वहां एक समाधान है।

आप FavoriteButton, environmentObject को ModelData के लिए जोड़ सकते हैं, और उस लैंडमार्क के सूचकांक की गणना करने के लिए एक गणना की गई संपत्ति जिसे आप LandmarkRow में उपयोग कर रहे हैं। यह मूल रूप से वही समाधान है जो LandmarkDetail में प्रयोग किया जाता है।

यह निम्नलिखित देता है:

struct LandmarkRow: View {
    // Access the modelData from the environment
    @EnvironmentObject var modelData: ModelData
    var landmark: Landmark

    // We need to get the index so that we can update the landmark in the ModelData
    var landmarkIndex: Int {
        modelData.landmarks.firstIndex(where: { $0.id == landmark.id })!
    }

    var body: some View {
        HStack {
            landmark.image
                .resizable()
                .frame(width: 50, height: 50)
            Text(landmark.name)

            Spacer()
            // Use the favorite button that already exists in the project
            FavoriteButton(isSet: $modelData.landmarks[landmarkIndex].isFavorite)
                .buttonStyle(PlainButtonStyle()) 
            // As LandmarkRow is used in a NavigationLink we need to set the 
            // buttonStyle so that we can use it otherwise we will just navigate.
        }
    }
}

struct LandmarkRow_Previews: PreviewProvider {
    static var landmarks = ModelData().landmarks

    static var previews: some View {
        Group {
            LandmarkRow(landmark: landmarks[0])
            LandmarkRow(landmark: landmarks[1])
        }
        .previewLayout(.fixed(width: 300, height: 70))
        .environmentObject(ModelData()) // Add the environmentObject so the previews will work
    }
}

फिर यदि आप देखना चाहते हैं कि आपके कितने पसंदीदा हैं, तो आप अपने LandmarkList में निम्न कार्य कर सकते हैं

var body: some View {
    NavigationView {
        List {
            Text("Favorites: \(modelData.landmarks.filter({$0.isFavorite}).count)")
            Toggle(isOn: $showFavoritesOnly) {
                Text("Favorites only")
            }

            ForEach(filteredLandmarks) { landmark in
                NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                    LandmarkRow(landmark: landmark)
                }
            }
        }
        .navigationTitle("Landmarks")
    }
}

ये परिवर्तन निम्नलिखित परिणाम देते हैं:

enter image description here

आईओएस 14.3 . के साथ एक्सकोड 12.3 में परीक्षण किया गया

0
Andrew 20 जिंदा 2021, 20:33