主頁 > 軟體工程 > SwiftUI:使用NavigationLink從一個視圖更改為另一個視圖時,復選標記消失

SwiftUI:使用NavigationLink從一個視圖更改為另一個視圖時,復選標記消失

2022-09-16 02:23:04 軟體工程

我正在嘗試制作一個應用程式,該應用程式根據單擊的 NavigationLink 顯示帶有選擇/復選標記的串列。我遇到的問題是,當我回傳主視圖然后我再次進入 NavigationLink 時,我的選擇消失了。我正在嘗試在 UserDefaults 中保存切換值,但它沒有按預期作業。下面我將粘貼詳細的主要內容視圖。

第二種觀點:

struct CheckView: View {
    
    @State var isChecked:Bool = false
    @EnvironmentObject var numofitems: NumOfItems
    
    var title:String
    var count: Int=0
    
    var body: some View {
        HStack{
            ScrollView {
                Toggle("\(title)", isOn: $isChecked)
                    .toggleStyle(CheckToggleStyle())
                    .tint(.mint)
                    .onChange(of: isChecked) { value in
                        
                        if isChecked {
                            numofitems.num  = 1
                            print(value)
                        } else{
                            numofitems.num -= 1
                        }
                        UserDefaults.standard.set(self.isChecked, forKey: "locationToggle")
                    }.onTapGesture {
                        
                    }
                    .onAppear {
                        self.isChecked = UserDefaults.standard.bool(forKey: "locationToggle")
                    }
                Spacer()
            }.frame(maxWidth: .infinity,alignment: .topLeading)
        }
    }
}

主視圖:

struct CheckListView: View {
    
    @State private var menu = Bundle.main.decode([ItemsSection].self, from: "items.json")
    
    
    var body: some View {
        NavigationView{
            List{
                ForEach(menu){
                    section in
                    NavigationLink(section.name) {
                        VStack{
                            ScrollView{
                                ForEach(section.items) { item in
                                    CheckView( title: item.name)
                                }
                            }
                        }
                    }
                }
            }
        }.navigationBarHidden(true)
            .navigationViewStyle(StackNavigationViewStyle())
            .listStyle(GroupedListStyle())
            .navigationViewStyle(StackNavigationViewStyle())
    }
}

物品欄目:

[
    {
        "id": "9DC6D7CB-B8E6-4654-BAFE-E89ED7B0AF94",
        "name": "Africa",
        "items": [
            {
                "id": "59B88932-EBDD-4CFE-AE8B-D47358856B93",
                "name": "Algeria"
            },
            {
                "id": "E124AA01-B66F-42D0-B09C-B248624AD228",
                "name": "Angola"
            }

模型:

struct ItemsSection: Codable, Identifiable, Hashable {
    var id: UUID = UUID()
    var name: String
    var items: [CountriesItem]
}

struct CountriesItem: Codable, Equatable, Identifiable,Hashable {
    var id: UUID = UUID()
    var name: String
}

uj5u.com熱心網友回復:

正如評論中所述,您必須將isChecked屬性與CountryItem自身相關聯。為了讓它作業,我改變了模型并添加了一個isChecked屬性。如果 JSON allread 存在,則需要手動將其添加到 JSON 中

struct CheckView: View {
    
    @EnvironmentObject var numofitems: NumOfItems
    //use a binding here as we are going to manipulate the data coming from  the parent
    //and pass the complete item not only the name
    @Binding var item: CountriesItem
        
    var body: some View {
        HStack{
            ScrollView {
                //use the name and the binding to the item itself
                Toggle("\(item.name)", isOn: $item.isChecked)
                    .toggleStyle(.button)
                    .tint(.mint)
                // you now need the observe the isChecked inside of the item
                    .onChange(of: item.isChecked) { value in
                        if value {
                            numofitems.num  = 1
                            print(value)
                        } else{
                            numofitems.num -= 1
                        }
                    }.onTapGesture {
                        
                    }
                Spacer()
            }.frame(maxWidth: .infinity,alignment: .topLeading)
        }
    }
}

struct CheckListView: View {
    
    @State private var menu = Bundle.main.decode([ItemsSection].self, from: "items.json")
    
    var body: some View {
        NavigationView{
            List{
                ForEach($menu){ // from here on you have to pass a binding on to the decendent views
                    // mark the $ sign in front of the property name
                    $section in
                    NavigationLink(section.name) {
                        VStack{
                            ScrollView{
                                ForEach($section.items) { $item in
                                    //Pass the complete item to the CheckView not only the name
                                    CheckView(item: $item)
                                }
                            }
                        }
                    }
                }
            }
        }.navigationBarHidden(true)
            .navigationViewStyle(StackNavigationViewStyle())
            .listStyle(GroupedListStyle())
            .navigationViewStyle(StackNavigationViewStyle())
    }
}

示例 JSON:

[
    {
        "id": "9DC6D7CB-B8E6-4654-BAFE-E89ED7B0AF94",
        "name": "Africa",
        "items": [
            {
                "id": "59B88932-EBDD-4CFE-AE8B-D47358856B93",
                "name": "Algeria",
                "isChecked": false
            },
            {
                "id": "E124AA01-B66F-42D0-B09C-B248624AD228",
                "name": "Angola",
                "isChecked": false
                
            }
        ]
    }
]

評論:

使用 JSON 并將其存盤在包中的方法將阻止您isChecked在應用程式啟動之間保留該屬性。因為您不能從您的應用程式中寫入 Bundle。只要應用程式處于活動狀態,該選擇就會一直存在,但一旦您重新安裝或強制退出它就會恢復默認設定。

uj5u.com熱心網友回復:

正如評論中已經提到的,我看不到您從 UserDefaults 中讀取的位置,因此無論存盤在那里,您都不會閱讀它。但即便如此,每個 Toggle 都使用相同的鍵,因此您正在覆寫該值。

我不會使用僅在本地使用的@State var isChecked,而是創建另一個結構項,該結構項從 json 獲取標題并包含一個用 false 初始化的布林值。

據我了解,我認為解決方案可能類似于以下代碼。只是幾件事:

  1. 我不確定你的 json 是什么樣子,所以我不是從 json 加載的,我添加了 ItemSections 帶有標題的物件和帶有函式的亂數量的專案(實際上只是標題)。
  2. 我在 UI 上添加了一個文本輸出,而不是帶有已檢查切換數量的列印。它在第一頁向您顯示所有已檢查切換的數量。
  3. 我沒有使用 UserDefaults,而是使用了 @AppStorage。要完成這項作業,您必須使Array符合RawRepresentable,您可以使用以下代碼/擴展來實作這一點(只需在專案中的某個位置添加一次)
  4. 也許您應該考慮 ViewModel(例如 ItemSectionViewModel),從 json 加載資料并將其作為 @ObservableObject 提供給視圖。

視圖的代碼:

//
//  CheckItem.swift
//  CheckItem
//
//  Created by Sebastian on 24.08.22.
//

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        VStack() {
            CheckItemView()
        }
    }
}

struct CheckItemView: View {
    
    let testStringForTestData: String = "Check Item Title"
    
    @AppStorage("itemSections") var itemSections: [ItemSection] = []
    
    func addCheckItem(title: String, numberOfItems: Int) {
        var itemArray: [Item] = []
        for i in 0...numberOfItems {
            itemArray.append(Item(title: "item \(i)"))
        }
        itemSections.append(ItemSection(title: title, items: itemArray))
    }
    
    func getSelectedItemsCount() -> Int{
        var i: Int = 0
        for itemSection in itemSections {
            let filteredItems = itemSection.items.filter { item in
                return item.isOn
            }
            i = i   filteredItems.count
        }
        return i
    }
    
    var body: some View {
        NavigationView{
            VStack() {
                List(){
                    ForEach(itemSections.indices, id: \.self){ id in
                        NavigationLink(destination: ItemSectionDetailedView(items: $itemSections[id].items)) {
                            Text(itemSections[id].title)
                        }
                        .padding()
                    }
                }
                Text("Number of checked items:  \(self.getSelectedItemsCount())")
                    .padding()
                
                Button(action: {
                    self.addCheckItem(title: testStringForTestData, numberOfItems: Int.random(in: 0..<4))
                }) {
                    Text("Add Item")
                }
                .padding()
            }
        }
    }
}

struct ItemSectionDetailedView: View {
    
    @Binding var items: [Item]
    
    var body: some View {
        ScrollView() {
            ForEach(items.indices, id: \.self){ id in
                Toggle(items[id].title, isOn: $items[id].isOn)
                    .padding()
            }
        }
    }
}

struct ItemSection: Identifiable, Hashable, Codable  {
    var id: String = UUID().uuidString
    var title: String
    var items: [Item]
}

struct Item: Identifiable, Hashable, Codable  {
    var id: String = UUID().uuidString
    var title: String
    var isOn: Bool = false
}

這里是使用@AppStorage 的調整:

extension Array: RawRepresentable where Element: Codable {
    public init?(rawValue: String) {
        guard let data = rawValue.data(using: .utf8),
              let result = try? JSONDecoder().decode([Element].self, from: data)
        else {
            return nil
        }
        self = result
    }
    
    public var rawValue: String {
        guard let data = try? JSONEncoder().encode(self),
              let result = String(data: data, encoding: .utf8)
        else {
            return "[]"
        }
        return result
    }
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/508521.html

標籤:IOS 迅速 苹果手机 迅捷

上一篇:支持if-elseios15或低于ios15

下一篇:具有onTapGesture功能的UI元素在Swift中不起作用

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more