Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用SwiftUI进行单选列表_Swift_List_Swiftui_Selection_Ios13 - Fatal编程技术网

如何使用SwiftUI进行单选列表

如何使用SwiftUI进行单选列表,swift,list,swiftui,selection,ios13,Swift,List,Swiftui,Selection,Ios13,我正在创建单个选择列表,以便在我的应用程序中的不同位置使用 问题: 有没有一个简单的解决办法我不知道 如果没有,我如何完成当前的解决方案 我的目标是: 始终仅选择一项或选择一项或无项的列表(取决于配置) 透明背景 在项上选择-执行通过init()方法设置为参数的操作。(该操作需要选定的项目信息。) 以编程方式更改列表数据并将所选内容重置为第一项 我当前的解决方案如下所示: 我不能使用选择器,因为外部操作(目标3)非常耗时。所以我认为它不会顺利运行。 我在SwiftUI中的问题很可能有解决方

我正在创建单个选择列表,以便在我的应用程序中的不同位置使用


问题:

有没有一个简单的解决办法我不知道

如果没有,我如何完成当前的解决方案


我的目标是:

  • 始终仅选择一项或选择一项或无项的列表(取决于配置)
  • 透明背景
  • 在项上选择-执行通过init()方法设置为参数的操作。(该操作需要选定的项目信息。)
  • 以编程方式更改列表数据并将所选内容重置为第一项
  • 我当前的解决方案如下所示:

    我不能使用选择器,因为外部操作(目标3)非常耗时。所以我认为它不会顺利运行。 我在SwiftUI中的问题很可能有解决方案,但要么我错过了,因为我是swift新手,要么因为我知道SwiftUI中并非所有东西都能完美工作,例如:列表的透明背景(这就是为什么我需要在init()中清除背景)

    所以我自己开始实施选择,并停在这里: 单击项目(按钮)时,我的当前解决方案不会更新视图。(仅进出页面更新视图)。而且仍然可以选择多个项目

    import SwiftUI
    
    struct ModuleList: View {
        var modules: [Module] = []
        @Binding var selectionKeeper: Int
        var Action: () -> Void
    
    
        init(list: [Module], selection: Binding<Int>, action: @escaping () -> Void) {
            UITableView.appearance().backgroundColor = .clear
            self.modules = list
            self._selectionKeeper = selection
            self.Action = action
        }
    
        var body: some View {
            List(){
                ForEach(0..<modules.count) { i in
                    ModuleCell(module: self.modules[i], action: { self.changeSelection(index: i) })
                    }
            }.background(Constants.colorTransparent)
        }
    
        func changeSelection(index: Int){
            modules[selectionKeeper].isSelected =  false
            modules[index].isSelected = true
            selectionKeeper = index
            self.Action()
        }
    }
    
    struct ModuleCell: View {
        var module: Module
        var Action: () -> Void
    
        init(module: Module, action: @escaping () -> Void) {
            UITableViewCell.appearance().backgroundColor = .clear
            self.module = module
            self.Action = action
        }
    
        var body: some View {
            Button(module.name, action: {
                self.Action()
            })
                .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                .modifier(Constants.CellSelection(isSelected: module.isSelected))
        }
    }
    
    class Module: Identifiable {
        var id = UUID()
        var name: String = ""
        var isSelected: Bool = false
        var address: Int
    
        init(name: String, address: Int){
            self.name = name
            self.address = address
        }
    }
    
    let testLines = [
        Module(name: "Line1", address: 1),
        Module(name: "Line2", address: 3),
        Module(name: "Line3", address: 5),
        Module(name: "Line4", address: 6),
        Module(name: "Line5", address: 7),
        Module(name: "Line6", address: 8),
        Module(name: "Line7", address: 12),
        Module(name: "Line8", address: 14),
        Module(name: "Line9", address: 11),
        Module(name: "Line10", address: 9),
        Module(name: "Line11", address: 22)
    ]
    
    struct ContentView: View {
        // Use Optional for selection.
        // Instead od Set or Array like this...
        // @State var selection = Set<Int>()
        @State var selection = Int?.none
        var body: some View {
            List(selection: $selection) {
                ForEach(0..<128) { _ in
                    Text("Sample")
                }
            }
        }
    }
    
    导入快捷界面
    结构模块列表:视图{
    变量模块:[模块]=[]
    @绑定变量selectionKeeper:Int
    var操作:()->Void
    初始化(列表:[模块],选择:绑定,操作:@escaping()->Void){
    UITableView.appearance().backgroundColor=.clear
    self.modules=list
    self.\u selectionKeeper=选择
    自我行动
    }
    var body:一些观点{
    列表(){
    ForEach(0..Void
    初始化(模块:模块,操作:@escaping()->Void){
    UITableViewCell.appearance().backgroundColor=.clear
    self.module=模块
    自我行动
    }
    var body:一些观点{
    按钮(模块名称、操作:{
    自我行动
    })
    .frame(最小宽度:0,最大宽度:。无穷大,对齐方式:。中心)
    .modifier(常数.CellSelection(isSelected:module.isSelected))
    }
    }
    类模块:可识别{
    var id=UUID()
    变量名称:String=“”
    var isSelected:Bool=false
    变量地址:Int
    init(名称:String,地址:Int){
    self.name=名称
    self.address=地址
    }
    }
    设测试线=[
    模块(名称:“Line1”,地址:1),
    模块(名称:“Line2”,地址:3),
    模块(名称:“Line3”,地址:5),
    模块(名称:“Line4”,地址:6),
    模块(名称:“Line5”,地址:7),
    模块(名称:“第6行”,地址:8),
    模块(名称:“Line7”,地址:12),
    模块(名称:“Line8”,地址:14),
    模块(名称:“Line9”,地址:11),
    模块(名称:“第10行”,地址:9),
    模块(名称:“Line11”,地址:22)
    ]
    

    测试一些想法: 尝试在ModuleList中添加@State数组of(isSelected:Bool),并将其绑定到可能更新视图的模块isSelected参数…但在init()中填充此数组失败,因为@State数组参数在.append()之后将保持为空…也许添加函数setList会解决这个问题,我的目标是4。但我不确定这是否真的会在第一时间更新我的视图

    struct ModuleList: View {
         var modules: [Module] = []
         @State var selections: [Bool] = []
    
    
         init(list: [String]) {
             UITableView.appearance().backgroundColor = .clear
             selections = [Bool] (repeating: false, count: list.count) // stays empty
             let test = [Bool] (repeating: false, count: list.count) // testing: works as it should
             selections = test
             for i in 0..<test.count { // for i in 0..<selections.count {
                 selections.append(false)
                 modules.append(Module(name: list[i], isSelected: $selections[i])) // Error selections is empty
             }
         }
    
         var body: some View {
             List{
                 ForEach(0..<modules.count) { i in
                     ModuleCell(module: self.modules[i], action: { self.changeSelection(index: i) })
                     }
             }.background(Constants.colorTransparent)
         }
         func changeSelection(index: Int){
             modules[index].isSelected = true
         }
     }
    
     struct ModuleCell: View {
         var module: Module
         var Method: () -> Void
    
         init(module: Module, action: @escaping () -> Void) {
             UITableViewCell.appearance().backgroundColor = .clear
             self.module = module
             self.Method = action
         }
    
         var body: some View {
             Button(module.name, action: {
                 self.Method()
             })
                 .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                 .modifier(Constants.CellSelection(isSelected: module.isSelected))
         }
     }
    
     struct Module: Identifiable {
         var id = UUID()
         var name: String = ""
         @Binding var isSelected: Bool
    
         init(name: String, isSelected: Binding<Bool>){
             self.name = name
             self._isSelected = isSelected
         }
     }
    
     let testLines = ["Line1","Line2","Line3","Line4"
     ]
    
    结构模块列表:视图{ 变量模块:[模块]=[] @状态变量选择:[Bool]=[] 初始化(列表:[字符串]){ UITableView.appearance().backgroundColor=.clear selections=[Bool](重复:false,count:list.count)//保持为空 让test=[Bool](重复:false,count:list.count)//测试:正常工作 选择=测试 对于0..Selection中的i SwiftUI目前没有一种内置的方法来选择列表中的一行并相应地更改其外观。但实际上,您已经非常接近您的答案。事实上,您的选择实际上已经起作用,但只是没有以任何方式使用

    为了进行说明,请在您的
    ForEach
    中的
    ModuleCell(…)
    之后添加以下行:

    .background(i == self.selectionKeeper ? Color.red : nil)
    
    换句话说,“如果我的当前行(
    i
    )与存储在
    selectionKeeper
    中的值匹配,则将单元格涂成红色,否则,使用默认颜色。”您将看到,当您点击不同的行时,红色会跟随您的点击,显示基本选择实际上正在改变

    取消选择 如果要启用取消选择,可以传入一个
    绑定
    作为选择,并在点击当前选定行时将其设置为
    nil

    struct ModuleList: View {
        var modules: [Module] = []
        // this is new ------------------v
        @Binding var selectionKeeper: Int?
        var Action: () -> Void
    
        // this is new ----------------------------v
        init(list: [Module], selection: Binding<Int?>, action: @escaping () -> Void) {
    
        ...
    
        func changeSelection(index: Int){
            if selectionKeeper != index {
                selectionKeeper = index
            } else {
                selectionKeeper = nil
            }
            self.Action()
        }
    }
    
    而您的
    ForEach
    看起来

    ForEach(0..<modules.count) { i in
        ModuleCell(module: self.modules[i],
                   isSelected: i == self.selectionKeeper,
                   action: { self.changeSelection(index: i) })
    }
    

    ForEach(0..实现这一点的最简单方法是在包含所选列表的视图中使用@State,并将其作为@Binding传递给单元格:

    struct SelectionView: View {
    
        let fruit = ["apples", "pears", "bananas", "pineapples"]
        @State var selectedFruit: String? = nil
    
        var body: some View {
            List {
                ForEach(fruit, id: \.self) { item in
                    SelectionCell(fruit: item, selectedFruit: self.$selectedFruit)
                }
            }
        }
    }
    
    struct SelectionCell: View {
    
        let fruit: String
        @Binding var selectedFruit: String?
    
        var body: some View {
            HStack {
                Text(fruit)
                Spacer()
                if fruit == selectedFruit {
                    Image(systemName: "checkmark")
                        .foregroundColor(.accentColor)
                }
            }   .onTapGesture {
                    self.selectedFruit = self.fruit
                }
        }
    }
    

    可选的
    类型选择变量一起使用绑定。
    
    列表
    将只允许选择一个元素

    import SwiftUI
    
    struct ModuleList: View {
        var modules: [Module] = []
        @Binding var selectionKeeper: Int
        var Action: () -> Void
    
    
        init(list: [Module], selection: Binding<Int>, action: @escaping () -> Void) {
            UITableView.appearance().backgroundColor = .clear
            self.modules = list
            self._selectionKeeper = selection
            self.Action = action
        }
    
        var body: some View {
            List(){
                ForEach(0..<modules.count) { i in
                    ModuleCell(module: self.modules[i], action: { self.changeSelection(index: i) })
                    }
            }.background(Constants.colorTransparent)
        }
    
        func changeSelection(index: Int){
            modules[selectionKeeper].isSelected =  false
            modules[index].isSelected = true
            selectionKeeper = index
            self.Action()
        }
    }
    
    struct ModuleCell: View {
        var module: Module
        var Action: () -> Void
    
        init(module: Module, action: @escaping () -> Void) {
            UITableViewCell.appearance().backgroundColor = .clear
            self.module = module
            self.Action = action
        }
    
        var body: some View {
            Button(module.name, action: {
                self.Action()
            })
                .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                .modifier(Constants.CellSelection(isSelected: module.isSelected))
        }
    }
    
    class Module: Identifiable {
        var id = UUID()
        var name: String = ""
        var isSelected: Bool = false
        var address: Int
    
        init(name: String, address: Int){
            self.name = name
            self.address = address
        }
    }
    
    let testLines = [
        Module(name: "Line1", address: 1),
        Module(name: "Line2", address: 3),
        Module(name: "Line3", address: 5),
        Module(name: "Line4", address: 6),
        Module(name: "Line5", address: 7),
        Module(name: "Line6", address: 8),
        Module(name: "Line7", address: 12),
        Module(name: "Line8", address: 14),
        Module(name: "Line9", address: 11),
        Module(name: "Line10", address: 9),
        Module(name: "Line11", address: 22)
    ]
    
    struct ContentView: View {
        // Use Optional for selection.
        // Instead od Set or Array like this...
        // @State var selection = Set<Int>()
        @State var selection = Int?.none
        var body: some View {
            List(selection: $selection) {
                ForEach(0..<128) { _ in
                    Text("Sample")
                }
            }
        }
    }
    
    struct ContentView:View{
    //使用可选选项进行选择。
    //而不是像这样的od集合或数组。。。
    //@State var selection=Set()
    @状态变量选择=Int?无
    var body:一些观点{
    列表(选择:$selection){
    
    ForEach(0..这里有一个更通用的方法,您仍然可以根据需要扩展答案

    TLDR


    细部

    struct SingleSelectionList:View{
    可变项目:[项目]
    @绑定变量selectedItem:Item?
    var rowContent:(项目)->Content
    var body:一些观点{
    列表(项目){中的项目
    行内容(项目)
    .modifier(CheckmarkModifier(选中:item.id==self.selectedItem?.id))
    .contentShape(矩形())
    .ontapsigne{
    self.selectedItem=项目
    }
    }
    }
    }
    结构CheckmarkModifier:ViewModifier{
    已检查变量:Bool=false
    func正文(内容:内容)->某些视图{
    团体{