Swiftui可以自动重新列出NSViewSrement

发布于 2025-01-22 00:28:16 字数 1591 浏览 0 评论 0原文

我已经在我的布局上引入了一个样式的NSView -reveRementable文本字段,以便使用属性的文本编辑器字段。我想通过一些按钮影响此文本字段的内容。

我可以更改该领域的样式属性,但是除非我手动击中它,否则它永远不会刷新。必须有一种自动执行此操作的方法。我错过了什么?

import SwiftUI
import Combine

let publisher = PassthroughSubject<Bool,Never>()

struct ContentView: View
{
    @State var mytext = NSMutableAttributedString(string: "")
    var attributedString: NSMutableAttributedString
    @State var textViewID: Int = 0
    
    init()
    {
        attributedString = NSMutableAttributedString(
            string: "Hello World!",
            attributes: [.font: NSFont.systemFont(ofSize: 18)])
        _mytext = State(initialValue: attributedString)
    }
    
    var body: some View
    {
        VStack
        {
            Button("Bold")
            {
                attributedString.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: 18), range: NSRange(location: 0, length: 5))
                mytext = attributedString
                publisher.send(true)
            }
        }
        TextView(text: $mytext)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .id(textViewID)
            .onReceive(publisher) { ( stateTo ) in
                textViewID += 1
            }

    }
}

struct TextView: NSViewRepresentable
{
    @Binding var text: NSMutableAttributedString
    
    func makeNSView(context: Context) -> NSTextView 
    {
        NSTextView()
    }
    
    func updateNSView(_ nsView: NSTextView, context: Context)
    {
        nsView.textStorage?.setAttributedString(text)
    }

}

还是我错过了一些东西,有一种简单的方法?

I have introduced a styled NSViewRepresentable text field on to my layout in order to use an attributed Text Editor field. I want to influence the content of this text field through some buttons.

I can change the styled attributes of the field, but it never refreshes unless I hit it manually. There must be a way of getting to do this automatically. What have I missed?

import SwiftUI
import Combine

let publisher = PassthroughSubject<Bool,Never>()

struct ContentView: View
{
    @State var mytext = NSMutableAttributedString(string: "")
    var attributedString: NSMutableAttributedString
    @State var textViewID: Int = 0
    
    init()
    {
        attributedString = NSMutableAttributedString(
            string: "Hello World!",
            attributes: [.font: NSFont.systemFont(ofSize: 18)])
        _mytext = State(initialValue: attributedString)
    }
    
    var body: some View
    {
        VStack
        {
            Button("Bold")
            {
                attributedString.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: 18), range: NSRange(location: 0, length: 5))
                mytext = attributedString
                publisher.send(true)
            }
        }
        TextView(text: $mytext)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .id(textViewID)
            .onReceive(publisher) { ( stateTo ) in
                textViewID += 1
            }

    }
}

struct TextView: NSViewRepresentable
{
    @Binding var text: NSMutableAttributedString
    
    func makeNSView(context: Context) -> NSTextView 
    {
        NSTextView()
    }
    
    func updateNSView(_ nsView: NSTextView, context: Context)
    {
        nsView.textStorage?.setAttributedString(text)
    }

}

Or am I missing something and there is a much easier way?

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

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

发布评论

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

评论(1

清引 2025-01-29 00:28:16

嫌疑人围绕着这个工作,并搬到了更大的鱼上。但是,为了使那些碰到类似事物的人的好处:-)

示例中代码的问题是,斯威夫特(Swiftui)没有什么可以用来确定何时需要重新绘制的。

具体来说,@State var mytext:nsmutableAttributedString属性string die持有对同一属性字符串的引用。因此,按钮操作myText =属性string来自Swiftui a noop的POV。

使其正常工作的两种方法。

首先,将同一字符串保留并突变到位,并且需要阐明。在这种情况下,可以清理按钮操作,以消除组合收割机的需求和on receive因此:

Button("Bold") {
   mytext.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: 18), range: NSRange(location: 0, length: 5))
   textViewID = mytext.hashValue
}

或其次,通过将突变删除到位,摆脱了合并,接管和ID属性的需求。取而代之的替换为Swiftui会注意到的新属性字符串,例如:

Button("Bold") {
   let newAttributedString:NSMutableAttributedString = mytext.mutableCopy() as! NSMutableAttributedString
   newAttributedString.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: 18), range: NSRange(location: 0, length: 5))
   mytext = newAttributedString
}

稍后可能会更惯用的Swiftui。

Suspect worked around this and moved onto bigger fish. But for the benefit of those bumping into something similar :-)

The problem with the code in the example is that there is nothing in it that SwiftUI can use to determine when it needs to redraw.

Specifically @State var mytext: NSMutableAttributedString is holding a reference to the same attributed string as attributedString does. Consequently the button action mytext = attributedString is from pov of SwiftUI a noop.

Two approaches to making it work.

First as now, where the same string is kept and mutated in place and a redraw is in effect explicity requested. In this case the Button action can be cleaned up to remove the need for Combine and the onReceive thus:

Button("Bold") {
   mytext.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: 18), range: NSRange(location: 0, length: 5))
   textViewID = mytext.hashValue
}

Or second, get rid of the need for Combine, onReceive and id attribute by removing the mutation in place. Instead replace with a new attribute string that SwiftUI will notice, e.g.:

Button("Bold") {
   let newAttributedString:NSMutableAttributedString = mytext.mutableCopy() as! NSMutableAttributedString
   newAttributedString.addAttribute(.font, value: NSFont.boldSystemFont(ofSize: 18), range: NSRange(location: 0, length: 5))
   mytext = newAttributedString
}

Later is probably slightly more idiomatic SwiftUI.

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