SwiftUI Bug – PlainButtonStyle Button 触发次数异常

Base on macOS 10.15, Xcode 11.7.

异常描述

1、当程序运行在非活跃状态时,且 NSWindow 为默认样式(可关闭、缩放、有标题栏等)。

此时如果点击 NSWindow 中的按钮,一般情况下会将该 NSWindow 变成活跃状态,同时触发按钮的 action 一次。但对于 PlainButtonStyle 样式的按钮,却无法触发其事件函数!

2、当程序运行在非活跃状态时,且 NSWindow 为空样式(styleMask = []),且允许拖动(isMovableByWindowBackground = true)。

此时如果点击 NSWindow 中的按钮,一般情况下会将该 NSWindow 变成活跃状态,同时触发按钮的 action 一次。但对于 PlainButtonStyle 样式的按钮,却会触发其事件函数两次!

测试代码

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Button("Normal") {
                NSLog("normal Button clicked")
            }
            
            Button(action: {
                NSLog("LinkButton clicked")
            }){
                Text("LinkButton")
            }.buttonStyle(LinkButtonStyle())
            
            Button(action: {
                NSLog("BorderedButton clicked")
            }){
                Text("BorderedButton")
            }.buttonStyle(BorderedButtonStyle())
            
            Button(action: {
                NSLog("BorderlessButton clicked")
            }){
                Text("BorderlessButton")
            }.buttonStyle(BorderlessButtonStyle())
            
            Button(action: {
                NSLog("PlainButton clicked")
            }){
                Text("PlainButton")
            }.buttonStyle(PlainButtonStyle())
            
        }.frame(width: 400, height: 300)
    }
}
import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!


    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

         // 👇 When App runs in backend, PlainButtonStyle Button could be triggered
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        
        // 👇 When App runs in backend, PlainButtonStyle Button trigger twice
//        window = NSWindow(
//            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
//            styleMask: [],
//            backing: .buffered, defer: false)
//        window.isMovableByWindowBackground = true
        
        
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }
}

 

解决办法

我把项目中的所有 PlainButtonStyle 按钮全部改成 BorderlessButtonStyle 了。

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top