DispatchQueue.main.async运行代码是否更慢?API闭包内创建标签问询
Great questions! Let's break them down one by one:
DispatchQueue.main.async cause performance slowdowns? The main queue is a serial queue dedicated to all UI updates and user interactions. Running code here won’t inherently slow things down—unless you’re dumping heavy, non-UI work (like complex calculations, parsing massive datasets, or image processing) onto it.
For lightweight tasks like creating a single label (as in your example), DispatchQueue.main.async is exactly where you should be running UI-related code (since all UI operations must happen on the main thread). The only time you’ll see slowdowns is if the main queue gets backed up with long-running tasks: since it’s serial, every subsequent task (including your label creation) has to wait its turn, which can make your app feel unresponsive or delay UI updates.
First, let’s look at your code snippet for context:
APIData().getRequest(epicGamesUsername: "test") { (output) in DispatchQueue.main.async { let winsLabelForProfile = Label().createLabel( labelText: output[0], font: "Avenir-HeavyOblique", fontSize: 45, center: center, centerX: centerX, centerY: centerY, offsetX: 0, offsetY: -(self.view.frame.width / 13), height: self.view.frame.width / 6, width: self.view.frame.width / 2, textAlignment: NSTextAlignme... ) } }
Here are the key issues and actionable fixes:
- Unsafe array access:
output[0]will crash immediately ifoutputis empty (e.g., if the API returns no data or an error). Always add a safety check first:guard let firstOutput = output.first else { // Handle empty state—show an error label, log a message, etc. return } let winsLabelForProfile = Label().createLabel(labelText: firstOutput, ...) - Risky hardcoded font name: Using a string like
"Avenir-HeavyOblique"is fragile—if the font isn’t available (unlikely for system fonts, but possible for custom ones), the system will fall back to a default font, breaking your design. Safely unwrap the font instead:guard let customFont = UIFont(name: "Avenir-HeavyOblique", size: 45) else { // Fallback to a reliable default let defaultFont = UIFont.systemFont(ofSize: 45, weight: .heavy) // Use defaultFont in your label setup return } - Fixed frame layout: Calculating size/position with
self.view.frame.widthwill break if the device rotates or the view’s layout changes (e.g., a navigation bar appears). Replace fixed frames with Auto Layout constraints for adaptive behavior:winsLabelForProfile.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(winsLabelForProfile) NSLayoutConstraint.activate([ winsLabelForProfile.centerXAnchor.constraint(equalTo: view.centerXAnchor), winsLabelForProfile.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -(view.frame.width / 13)), winsLabelForProfile.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5), winsLabelForProfile.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/6) ]) - Potential retain cycle: If
APIData.getRequestholds a strong reference to its closure, and the closure capturesselfstrongly, you’ll create a memory leak. Use aweakreference toself:APIData().getRequest(epicGamesUsername: "test") { [weak self] (output) in guard let self = self else { return } // Avoid optional self later DispatchQueue.main.async { // Your label code here, using self safely } } - Missing view addition: Your code creates the label but doesn’t add it to the view hierarchy (unless you omitted that part). Don’t forget to call
self.view.addSubview(winsLabelForProfile)after creating the label. - Truncated parameter: Finish the
textAlignmentvalue (e.g.,NSTextAlignment.centerinstead ofNSTextAlignme...).
内容的提问来源于stack exchange,提问作者Julian L

