将操作添加到使用UiviewRementable创建的按钮

发布于 2025-01-25 19:32:38 字数 3056 浏览 3 评论 0原文

我正在使用a fluentui#fulentui#button#button /a>,在使用Uikit的背后

,我需要在SwiftUi视图中显示该按钮,并且我正在尝试切换@State属性或添加#selector该按钮,但是我无法做到这一点,

我创建了一个通用uiviewRementable结构,以帮助我在SwiftUi视图中嵌入任何Uiview,之后 tutorial

struct Anything<Wrapper : UIView>: UIViewRepresentable {
    typealias Updater = (Wrapper, Context) -> Void

    var makeView: () -> Wrapper
    var update: (Wrapper, Context) -> Void

    init(_ makeView: @escaping @autoclosure () -> Wrapper,
         updater update: @escaping (Wrapper) -> Void) {
        self.makeView = makeView
        self.update = { view, _ in update(view) }
    }

    func makeUIView(context: Context) -> Wrapper {
        makeView()
    }

    func updateUIView(_ view: Wrapper, context: Context) {
        update(view, context)
    }
}

我有以下代码:

import SwiftUI
import FluentUI

struct MyView: View {
    @State var isGreen = true
    
    var body: some View {
        VStack {
            Text("Hello, World!")
                .background(isGreen ? Color.green : Color.blue)
            Spacer().frame(height: 20)
            Anything(FluentUI.Button(style: .primaryFilled)) {
                $0.setTitle("Try me!", for: .normal)
            }
            .frame(height: 30)
            .padding()
        }
    }
}

struct Anything<Wrapper: UIView>: UIViewRepresentable {
    typealias Updater = (Wrapper, Context) -> Void

    var makeView: () -> Wrapper
    var update: (Wrapper, Context) -> Void
    var action: (() -> Void)?

    init(_ makeView: @escaping @autoclosure () -> Wrapper,
         updater update: @escaping (Wrapper) -> Void) {
        self.makeView = makeView
        self.update = { view, _ in update(view) }
    }

    func makeUIView(context: Context) -> Wrapper {
        makeView()
    }

    func updateUIView(_ view: Wrapper, context: Context) {
        update(view, context)
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        MyView()
    }
}

如果我尝试添加以下添加:我

$0.addTarget(self, action: #selector(toggleColor), for: .touchUpInside)

得到:

func toggleColor() {
    isGreen = !isGreen
}

我得到此错误:我得到此错误:

Argument of '#selector' refers to instance method 'toggleColor()' that is not exposed to Objective-C

而且,如果我将@OBJC添加到该方法中,我会收到此错误:

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

并且由于我的 struct不是button swiftui,我无法将操作参数添加为通常

如何以这种方式添加目标/操作?

I am using a FluentUI#button, which behind uses UIKit

I need to display that button in a SwiftUI View, and I'm trying to toggle an @State property or add a #selector to the button, but I'm not able to do it

I created a generic UIViewRepresentable structure to help me embed any UIView in my SwiftUI Views, following this tutorial:

struct Anything<Wrapper : UIView>: UIViewRepresentable {
    typealias Updater = (Wrapper, Context) -> Void

    var makeView: () -> Wrapper
    var update: (Wrapper, Context) -> Void

    init(_ makeView: @escaping @autoclosure () -> Wrapper,
         updater update: @escaping (Wrapper) -> Void) {
        self.makeView = makeView
        self.update = { view, _ in update(view) }
    }

    func makeUIView(context: Context) -> Wrapper {
        makeView()
    }

    func updateUIView(_ view: Wrapper, context: Context) {
        update(view, context)
    }
}

And I have the following code:

import SwiftUI
import FluentUI

struct MyView: View {
    @State var isGreen = true
    
    var body: some View {
        VStack {
            Text("Hello, World!")
                .background(isGreen ? Color.green : Color.blue)
            Spacer().frame(height: 20)
            Anything(FluentUI.Button(style: .primaryFilled)) {
                $0.setTitle("Try me!", for: .normal)
            }
            .frame(height: 30)
            .padding()
        }
    }
}

struct Anything<Wrapper: UIView>: UIViewRepresentable {
    typealias Updater = (Wrapper, Context) -> Void

    var makeView: () -> Wrapper
    var update: (Wrapper, Context) -> Void
    var action: (() -> Void)?

    init(_ makeView: @escaping @autoclosure () -> Wrapper,
         updater update: @escaping (Wrapper) -> Void) {
        self.makeView = makeView
        self.update = { view, _ in update(view) }
    }

    func makeUIView(context: Context) -> Wrapper {
        makeView()
    }

    func updateUIView(_ view: Wrapper, context: Context) {
        update(view, context)
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        MyView()
    }
}

And if I try to add this:

$0.addTarget(self, action: #selector(toggleColor), for: .touchUpInside)

With:

func toggleColor() {
    isGreen = !isGreen
}

I get this error:

Argument of '#selector' refers to instance method 'toggleColor()' that is not exposed to Objective-C

And if I add @objc to the method I get this error:

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

And as my Anything struct isn't a Button from SwiftUI, I cannot add the action parameter as normally

How can I add a target/action to my button in this way?

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

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

发布评论

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

评论(1

疏忽 2025-02-01 19:32:38

这是可能的解决方案的演示 - 我们需要Uikit Objective -C选择器和SwiftUI Swift功能之间的包装器。

用Xcode 13.3/ios 15.4

“

这是主要部分(用于简单的uibutton而不是fluentui.button):

Anything(UIButton(type: .system)) {
    $0.setTitle("Try me!", for: .normal)

    $0.addTarget(toggleColor, action: #selector(Action.perform(sender:)), for: .touchUpInside)
    toggleColor.action = {
        isGreen.toggle()
    }
}

完整的测试模块在这里

Here is a demo of possible solution - we need a wrapper between UIKit objective-c selectors and SwiftUI swift function.

Tested with Xcode 13.3 / iOS 15.4

demo

Here is main part (used UIButton instead of FluentUI.Button for simplicity):

Anything(UIButton(type: .system)) {
    $0.setTitle("Try me!", for: .normal)

    $0.addTarget(toggleColor, action: #selector(Action.perform(sender:)), for: .touchUpInside)
    toggleColor.action = {
        isGreen.toggle()
    }
}

Complete test module is here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文