在UIKit中使用SwiftUI-使用UIKit中的数据?

62lalag4  于 2023-02-28  发布在  Swift
关注(0)|答案(2)|浏览(160)

我的UIKit应用程序中显示了基于数据的SwiftUI视图。我想做的是基于UIKit中的按钮点击更改SwiftUI视图,只是为了测试。我还不太擅长绑定。现在在我的按钮代码中,我不确定如何影响更改(即突出显示第二项)。
以下是我当前的设置:

struct PresetBank: Identifiable
{
    var id: UUID
    let index: Int
    var title: String
    var iconString: String
    var presetsCount: Int
    var isSelected: Bool = false
}

class PresetStore: ObservableObject
{
    @Published var arrayOfPresets: [PresetBank]
    init(arrayOfPresets: [PresetBank]) {
        self.arrayOfPresets = arrayOfPresets
    }
    public func selectBank(index: Int) {
        print(index)
        // How can I change the PresetBank items isSelected
        // in order to update their UI? I can loop through
        // and change the prop, but it does nothing.
        for i in 0..<arrayOfPresets.count - 1 {
            arrayOfPresets[i].isSelected = false
        }
        arrayOfPresets[index].isSelected = true
        // The properties change, but the UI does not update.
        // I am missing something here.
    }
}

struct PresetBankView: View
{
    var bank: PresetBank
    @State var isSelected: Bool
    
    var body: some View
    {
        ZStack
        {
            VStack {
                Text(bank.title)
                    .multilineTextAlignment(.center)
                    .fontWeight(.medium)
                    .foregroundColor(bank.isSelected == true ? .white : .black)
                    .font(.system(size: 12))
                    .minimumScaleFactor(0.5)
                    .lineLimit(2)
                    .padding(.top, 10)
                    .padding(.leading, 5)
                    .padding(.trailing, 5)
                Spacer()
                Text("\(bank.presetsCount)")
                    .multilineTextAlignment(.center)
                    .font(.system(size: 10))
                    .foregroundColor(bank.isSelected == true ? .white : .black)
                    .padding(.bottom, 10)
            }
            ZStack {
                    Image(systemName: bank.iconString)
                        .font(.system(size: 26))
                        .foregroundColor(bank.isSelected == true ? .white : .black)
               
                
            }.padding(.top, 10)
        }
        .frame(width: 100, height: 100)
        .background {
            RoundedRectangle(cornerRadius: 8)
               .aspectRatio(contentMode: .fill)
               .foregroundColor(bank.isSelected == true ? .black : .white)
               .shadow(color: .black.opacity(0.3), radius: 5, x: 0, y: 0)
               .overlay(
                    RoundedRectangle(cornerRadius: 8)
                        .stroke(.gray, lineWidth: 2)
                )
        }
        Spacer()
            .frame(width: 15)
    }
}

struct ContentView: View
{
    @State var store: PresetStore
    var body: some View
    {
        ScrollView(.horizontal)
        {
            HStack {
                
                // Pull in and use the data passed in from UIKit.
                
                ForEach(store.arrayOfPresets) { bank in
                    PresetBankView(bank: bank, isSelected: bank.isSelected)
                }
            }
            .padding()
        }
    }
}
...
class ViewController: UIViewController
{
    var thisStore: PresetStore!
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        let arrayOfPresets:[PresetBank] = []
        thisStore = PresetStore(arrayOfPresets: arrayOfPresets)
        
        let p1: PresetBank = PresetBank(id: UUID(), index: 0, title: "Default", iconString: "music.note.house", presetsCount: 5, isSelected: true)
        let p2: PresetBank = PresetBank(id: UUID(), index: 1, title: "Relaxation", iconString: "figure.mind.and.body", presetsCount: 2)
        let p3: PresetBank = PresetBank(id: UUID(), index: 2, title: "Dinner Party on Sunday Afternoon", iconString: "wineglass.fill", presetsCount: 3)
        let p4: PresetBank = PresetBank(id: UUID(), index: 3, title: "Workout", iconString: "figure.run", presetsCount: 5)
        let p5: PresetBank = PresetBank(id: UUID(), index: 4, title: "Sleepy Time", iconString: "powersleep", presetsCount: 2)
        
        thisStore.arrayOfPresets.append(p1)
        thisStore.arrayOfPresets.append(p2)
        thisStore.arrayOfPresets.append(p3)
        thisStore.arrayOfPresets.append(p4)
        thisStore.arrayOfPresets.append(p5)
        
        let contentView = UIHostingController(rootView: ContentView(store: thisStore))
        addChild(contentView)
        view.addSubview(contentView.view)
        contentView.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 200)
    }
    
    @IBAction func testSelect(_ sender: UIButton) {
        thisStore.selectBank(index: 1)

    }
}

所以你可以在selectBank方法中看到我想要遍历所有的PresetBank并将它们的isSelected更改为false,然后通过索引将一个设置为true-并更新视图,目前我还不清楚如何实现这一点。

tjvv9vkg

tjvv9vkg1#

我认为这解决了问题。下面是我更新的代码:

class ViewController: UIViewController
{
    var thisStore: PresetStore!
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        let arrayOfPresets:[PresetBank] = []
        thisStore = PresetStore(arrayOfPresets: arrayOfPresets)
        
        let p1: PresetBank = PresetBank(id: UUID(), index: 0, title: "Default", iconString: "music.note.house", presetsCount: 5, isSelected: true)
        let p2: PresetBank = PresetBank(id: UUID(), index: 1, title: "Relaxation", iconString: "figure.mind.and.body", presetsCount: 2, isSelected: false)
        let p3: PresetBank = PresetBank(id: UUID(), index: 2, title: "Dinner Party on Sunday Afternoon", iconString: "wineglass.fill", presetsCount: 3, isSelected: false)
        let p4: PresetBank = PresetBank(id: UUID(), index: 3, title: "Workout", iconString: "figure.run", presetsCount: 5, isSelected: false)
        let p5: PresetBank = PresetBank(id: UUID(), index: 4, title: "Sleepy Time", iconString: "powersleep", presetsCount: 2, isSelected: false)
        
        thisStore.arrayOfPresets.append(p1)
        thisStore.arrayOfPresets.append(p2)
        thisStore.arrayOfPresets.append(p3)
        thisStore.arrayOfPresets.append(p4)
        thisStore.arrayOfPresets.append(p5)
        
        let contentView = UIHostingController(rootView: ContentView(store: thisStore))
        addChild(contentView)
        view.addSubview(contentView.view)
        contentView.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 200)
    }
    
    @IBAction func testSelect(_ sender: UIButton) {
        thisStore.selectBank(index: sender.tag)
    }
}

class PresetBank: Identifiable, ObservableObject
{
    var id: UUID = UUID()
    let index: Int
    var title: String
    var iconString: String
    var presetsCount: Int
    @Published var isSelected: Bool = false
    init(id:UUID, index:Int, title:String, iconString:String, presetsCount:Int, isSelected:Bool){
        self.id = id
        self.index = index
        self.title = title
        self.iconString = iconString
        self.presetsCount = presetsCount
        self.isSelected = isSelected
    }
}

class PresetStore: ObservableObject
{
    @Published var arrayOfPresets: [PresetBank]
    init(arrayOfPresets: [PresetBank]) {
        self.arrayOfPresets = arrayOfPresets
    }
    public func selectBank(index: Int) {
        print(index)
        // How can I change the PresetBank items isSelected
        // in order to update their UI? I can loop through
        // and change the prop, but it does nothing.
        for i in 0..<arrayOfPresets.count - 1 {
            arrayOfPresets[i].isSelected = false
        }
        arrayOfPresets[index].isSelected = true
        print(arrayOfPresets)
        // Above works, but the change doesn't affect the UI.
    }
}

struct PresetBankView: View
{
    @ObservedObject var bank: PresetBank
    @State var isSelected: Bool
    
    var body: some View
    {
        ZStack
        {
            VStack {
                Text(bank.title)
                    .multilineTextAlignment(.center)
                    .fontWeight(.medium)
                    .foregroundColor(bank.isSelected == true ? .white : .black)
                    .font(.system(size: 12))
                    .minimumScaleFactor(0.5)
                    .lineLimit(2)
                    .padding(.top, 10)
                    .padding(.leading, 5)
                    .padding(.trailing, 5)
                Spacer()
                Text("\(bank.presetsCount)")
                    .multilineTextAlignment(.center)
                    .font(.system(size: 10))
                    .foregroundColor(bank.isSelected == true ? .white : .black)
                    .padding(.bottom, 10)
            }
            ZStack {
                    Image(systemName: bank.iconString)
                        .font(.system(size: 26))
                        .foregroundColor(bank.isSelected == true ? .white : .black)
               
                
            }.padding(.top, 10)
        }
        .frame(width: 100, height: 100)
        .background {
            RoundedRectangle(cornerRadius: 8)
               .aspectRatio(contentMode: .fill)
               .foregroundColor(bank.isSelected == true ? .black : .white)
               .shadow(color: .black.opacity(0.3), radius: 5, x: 0, y: 0)
               .overlay(
                    RoundedRectangle(cornerRadius: 8)
                        .stroke(.gray, lineWidth: 2)
                )
        }
        Spacer()
            .frame(width: 15)
    }
}

struct ContentView: View
{
    @State var store: PresetStore
    var body: some View
    {
        ScrollView(.horizontal)
        {
            HStack {
                
                // Pull in and use the data passed in from UIKit.
                
                ForEach(store.arrayOfPresets) { bank in
                    PresetBankView(bank: bank, isSelected: bank.isSelected)
                }
            }
            .padding()
        }
    }
}

现在从UIKit更新很好。我有3个测试按钮,并循环通过SwiftUI视图isSelected属性。接下来让SwiftUI更新自己和UIKit。

qqrboqgw

qqrboqgw2#

您可以像这样替换宿主控制器上的数据结构:

@IBAction func testSelect(_ sender: UIButton) {
    hostingController.rootView = ContentView(bank:  thisStore[sender.tag])
}

相关问题