将Swiftui选择器与课堂

发布于 2025-02-06 06:36:06 字数 1934 浏览 1 评论 0原文

我一直在努力让选择器从数组中返回对象。我的印象是,我要做的就是将对象作为标签包括在内,而选择最终将作为该对象。显然不是。任何帮助将不胜感激。

我的实际应用使用从Coredata提取的信息。

该测试应用程序中的预期结果是将选择的选择显示了做出选择的项目的右侧。


import SwiftUI

class Choice: Identifiable, Hashable
{
    let id: UUID
    var name = ""
    
    init()
    {
        self.id = UUID()
    }
    
    init(_ name: String)
    {
        self.id = UUID()
        self.name = name
    }
    
    static func == (lhs: Choice, rhs: Choice) -> Bool
    {
        return lhs.name < rhs.name
    }
    
    func hash(into hasher: inout Hasher)
    {
        hasher.combine(name)
    }
    
}

class Stuff: Identifiable
{
    let id: UUID
    var title: String
    var choice: Choice?
    
    init(_ title: String)
    {
        self.id = UUID()
        self.title = title
    }
}

struct ContentView: View
{
    let items = [Stuff("ABC"), Stuff("XYZ")]
    let choices = [Choice("ONE"),Choice("Two"), Choice("Three)")]
    
    @State var choice: Choice?
    
    var body: some View
    {
        VStack
        {
            ForEach(items)
            { item in
                HStack
                {
                    Text(item.title)
                    Picker("Choice", selection: $choice)
                    {
                        ForEach(choices)
                        {
                            c in
                            Text(c.name).tag(c)
                        }
                    }
                }
            }
            Spacer()
            ForEach(items)
            {
                item in
                HStack
                {
                    Text(item.title)
                    Spacer()
                    if let c = item.choice
                    {
                        Text(c.name)
                    } else
                    {
                        Text("No choice")
                    }
                }
            }
        }
    }
}

I've been struggling to get Picker to return an object from an array. I was of the impression that all I needed to do was include the object as a tag and the selection would end up as that object. Apparently not. Any help would be greatly appreciated.

My actual app uses information extracted from CoreData.

The expected result in this test app is to show the selection to the right of the item where the choice was made.


import SwiftUI

class Choice: Identifiable, Hashable
{
    let id: UUID
    var name = ""
    
    init()
    {
        self.id = UUID()
    }
    
    init(_ name: String)
    {
        self.id = UUID()
        self.name = name
    }
    
    static func == (lhs: Choice, rhs: Choice) -> Bool
    {
        return lhs.name < rhs.name
    }
    
    func hash(into hasher: inout Hasher)
    {
        hasher.combine(name)
    }
    
}

class Stuff: Identifiable
{
    let id: UUID
    var title: String
    var choice: Choice?
    
    init(_ title: String)
    {
        self.id = UUID()
        self.title = title
    }
}

struct ContentView: View
{
    let items = [Stuff("ABC"), Stuff("XYZ")]
    let choices = [Choice("ONE"),Choice("Two"), Choice("Three)")]
    
    @State var choice: Choice?
    
    var body: some View
    {
        VStack
        {
            ForEach(items)
            { item in
                HStack
                {
                    Text(item.title)
                    Picker("Choice", selection: $choice)
                    {
                        ForEach(choices)
                        {
                            c in
                            Text(c.name).tag(c)
                        }
                    }
                }
            }
            Spacer()
            ForEach(items)
            {
                item in
                HStack
                {
                    Text(item.title)
                    Spacer()
                    if let c = item.choice
                    {
                        Text(c.name)
                    } else
                    {
                        Text("No choice")
                    }
                }
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼眸里的那抹悲凉 2025-02-13 06:36:07

选择和标签应按类型匹配,目前不匹配,因此

// give initial value (anyway first is by default)
@State var choice: Choice = Choice("ONE")  // << here !!

时还需要修复修复

static func == (lhs: Choice, rhs: Choice) -> Bool
{
    return lhs.name == rhs.name    // << here !!
}

在用Xcode 13.4 / ios 15.5进行测试

Selection and tag should match by type, currently they are not, so fix is

// give initial value (anyway first is by default)
@State var choice: Choice = Choice("ONE")  // << here !!

also correction needed in

static func == (lhs: Choice, rhs: Choice) -> Bool
{
    return lhs.name == rhs.name    // << here !!
}

Tested with Xcode 13.4 / iOS 15.5

丶情人眼里出诗心の 2025-02-13 06:36:07

下面的建议肯定有所帮助,但正如指出的那样,有几个错误/假设使原始方法粗略。我通过创建一个单独的视图来展示每行/(列表项目)并将选择器分开,从而结合了建议并更改了策略。

import SwiftUI

struct Choice: Identifiable, Hashable
{
    let id: UUID
    var name = ""
    
    init()
    {
        self.id = UUID()
    }
    
    init(_ name: String)
    {
        self.id = UUID()
        self.name = name
    }
    
    static func == (lhs: Choice, rhs: Choice) -> Bool
    {
        return lhs.name == rhs.name
    }
    
    func hash(into hasher: inout Hasher)
    {
        hasher.combine(name)
    }
    
}

struct Stuff: Identifiable
{
    let id: UUID
    var title: String
    var choice: Choice?
    
    init(_ title: String)
    {
        self.id = UUID()
        self.title = title
    }
}

struct ContentView: View
{
    @State var items = [Stuff("ABC"), Stuff("XYZ")]
    
    @State var idx = 0
    
    var body: some View
    {
        VStack
        {
            ForEach($items)
            { $item in
                ItemLine(item: $item)
            }
            Spacer()
            ForEach(items)
            {
                item in
                HStack
                {
                    Text(item.title)
                    Spacer()
                    if let c = item.choice
                    {
                        Text(c.name)
                    } else
                    {
                        Text("No choice")
                    }
                }
            }.id(idx)
            Button("Refresh")
            {
                idx = idx + 1
            }
        }.padding()
    }
    
    struct ItemLine: View
    {
        @Binding var item: Stuff
        
        let choices = [Choice("One"),Choice("Two"), Choice("Three")]
        
        var body: some View
        {
            HStack
            {
                Text(item.title)
                Picker("Choice", selection: $item.choice)
                {
                    ForEach(choices)
                    {
                        c in
                        Text(c.name).tag(Optional(c))
                    }
                }
            }
        }
    }
}

The below suggestions definitely helped but as pointed out, there were several errors/assumptions that made the original approach sketchy. I have incorporated the suggestions and changed strategy by creating a separate view to present each line/(list item) and to separate the pickers.

import SwiftUI

struct Choice: Identifiable, Hashable
{
    let id: UUID
    var name = ""
    
    init()
    {
        self.id = UUID()
    }
    
    init(_ name: String)
    {
        self.id = UUID()
        self.name = name
    }
    
    static func == (lhs: Choice, rhs: Choice) -> Bool
    {
        return lhs.name == rhs.name
    }
    
    func hash(into hasher: inout Hasher)
    {
        hasher.combine(name)
    }
    
}

struct Stuff: Identifiable
{
    let id: UUID
    var title: String
    var choice: Choice?
    
    init(_ title: String)
    {
        self.id = UUID()
        self.title = title
    }
}

struct ContentView: View
{
    @State var items = [Stuff("ABC"), Stuff("XYZ")]
    
    @State var idx = 0
    
    var body: some View
    {
        VStack
        {
            ForEach($items)
            { $item in
                ItemLine(item: $item)
            }
            Spacer()
            ForEach(items)
            {
                item in
                HStack
                {
                    Text(item.title)
                    Spacer()
                    if let c = item.choice
                    {
                        Text(c.name)
                    } else
                    {
                        Text("No choice")
                    }
                }
            }.id(idx)
            Button("Refresh")
            {
                idx = idx + 1
            }
        }.padding()
    }
    
    struct ItemLine: View
    {
        @Binding var item: Stuff
        
        let choices = [Choice("One"),Choice("Two"), Choice("Three")]
        
        var body: some View
        {
            HStack
            {
                Text(item.title)
                Picker("Choice", selection: $item.choice)
                {
                    ForEach(choices)
                    {
                        c in
                        Text(c.name).tag(Optional(c))
                    }
                }
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文