MacOS Swift应用点击添加标签功能代码编译通过但崩溃求助
Hey Marco, let's dig into why your code is crashing and fix it step by step. I spotted a few key issues that are causing the crash and preventing your text fields from showing up properly:
1. Undefined location Variable
Your code references self.location but never actually retrieves the mouse click position from the NSEvent. This is definitely causing a crash because the variable doesn't exist. Instead, you need to get the click location directly from the event passed to the monitor closure.
2. Misused @IBOutlet for the Text Field Array
@IBOutlet is meant for connecting UI elements from Storyboard/XIB files to your code. Since you're creating text fields programmatically, you don't need this annotation—just declare a regular array to hold your text fields. Using @IBOutlet here can lead to unexpected memory or initialization issues.
3. Forgetting to Add Text Fields to the View
Even if you create the NSTextField instances, they won't appear (and might cause memory-related crashes) unless you add them as subviews to your window's content view.
4. Redundant count Variable
You're manually tracking a count variable, but you can just use here2.count directly—this avoids synchronization issues where count might not match the actual array size.
Fixed Code
Here's the revised, crash-free version of your code with explanations in comments:
// Remove @IBOutlet since we're creating text fields programmatically var here2 = [NSTextField]() override func viewDidLoad() { super.viewDidLoad() // Set up the mouse event monitor in a proper lifecycle method setupMouseClickMonitor() } func setupMouseClickMonitor() { NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown) { [weak self] event in guard let self = self else { return event } // Get the click position relative to the window's content view let clickLocation = event.locationInWindow // Convert to the view's coordinate system for accurate positioning let viewLocation = self.view.convert(clickLocation, from: nil) // Check if the click is within your desired bounds if viewLocation.x < 700 && viewLocation.y < 750 { // Create a new text field let newTextField = NSTextField() // Set position and size (adjust size as needed) newTextField.frame = CGRect(origin: viewLocation, size: CGSize(width: 80, height: 24)) // Set text to the current array count (no need for a separate variable) newTextField.stringValue = String(self.here2.count) // Make the text field visible (default style is hard to see) newTextField.borderStyle = .lineBorder newTextField.drawsBackground = true newTextField.backgroundColor = .white // Add the text field to the view so it renders on screen self.view.addSubview(newTextField) // Store it in the array for future reference self.here2.append(newTextField) print("count is: \(self.here2.count)") } return event } }
Key Fixes Explained:
[weak self]in the closure: Prevents retain cycles that could cause memory leaks or crashes over time.- Proper location retrieval: Uses
event.locationInWindowand converts it to the view's coordinate system for accurate positioning. - Added view insertion:
self.view.addSubview(newTextField)ensures the text field is rendered on screen. - Removed redundant
countvariable: Useshere2.countdirectly to keep track of the number of text fields. - Visible text field setup: Added border and background so you can actually see the text field when it's created.
内容的提问来源于stack exchange,提问作者marco

