iOS中UIScrollView仅显示最后添加视图的问题排查求助
Hey there, let's break down what's going wrong with your code and fix it step by step.
Core Issues in Your Code
1. Conflict Between AutoLayout and Manual Frame Setting
You set walletView.translatesAutoresizingMaskIntoConstraints = false, which tells iOS to use AutoLayout for this view. But then you manually set the frame—and didn't add any AutoLayout constraints to define the view's position/size. Without constraints, iOS doesn't know where to place these views, so all your Wallet views end up overlapping at the (0,0) position of accountSavingSubView. Only the last one you add is visible on top.
2. Wrong yPosition Calculation
Your line yPosition += walletView.frame.maxY is causing the y-coordinate to grow way too fast:
- First view: y=0, maxY = view height
h→ yPosition becomesh - Second view: y=
h, maxY =h + h = 2h→ yPosition becomesh + 2h = 3h - Third view: y=
3h, maxY =3h + h = 4h→ yPosition becomes3h + 4h =7h
This pushes later views way off-screen, while earlier ones are stuck at (0,0) due to the AutoLayout conflict.
Fixes to Try
Option 1: Use AutoLayout (Recommended for Modern iOS)
Since you're already enabling AutoLayout, let's use proper constraints to position your Wallet views:
private func createAndAddWallets() { var previousWallet: UIView? = nil for key in dictData.keys { // Load the Wallet nib with safe unwrapping guard let walletView = Bundle.main.loadNibNamed("Wallet", owner: self, options: nil)?.first as? Wallet else { continue // Add error handling here if needed } walletView.translatesAutoresizingMaskIntoConstraints = false walletView.accountNameLabel.text = key walletView.isUserInteractionEnabled = true accountSavingSubView.addSubview(walletView) // Pin width to accountSavingSubView, set height (match subview or use fixed value) NSLayoutConstraint.activate([ walletView.leadingAnchor.constraint(equalTo: accountSavingSubView.leadingAnchor), walletView.trailingAnchor.constraint(equalTo: accountSavingSubView.trailingAnchor), walletView.heightAnchor.constraint(equalTo: accountSavingSubView.heightAnchor) ]) // Vertical positioning: stack views one after another if let prevWallet = previousWallet { walletView.topAnchor.constraint(equalTo: prevWallet.bottomAnchor).isActive = true } else { walletView.topAnchor.constraint(equalTo: accountSavingSubView.topAnchor).isActive = true } previousWallet = walletView print("walletView frame: \(walletView.frame)") } // Pin the last wallet to the bottom of accountSavingSubView so scrollView calculates contentSize automatically if let lastWallet = previousWallet { lastWallet.bottomAnchor.constraint(equalTo: accountSavingSubView.bottomAnchor).isActive = true } // No need to manually set contentSize—AutoLayout handles it if your scrollView's constraints are set up correctly }
Option 2: Stick to Frame Layout (If You Prefer)
If you want to use manual frame setting, turn off AutoLayout for the Wallet views and fix the yPosition logic:
private func createAndAddWallets() { var yPosition: CGFloat = 0.0 let walletWidth = accountSavingSubView.frame.width let walletHeight = accountSavingSubView.frame.height for key in dictData.keys { guard let walletView = Bundle.main.loadNibNamed("Wallet", owner: self, options: nil)?.first as? Wallet else { continue } // Enable autoresizing masks so frame settings work walletView.translatesAutoresizingMaskIntoConstraints = true walletView.frame = CGRect(x: 0, y: yPosition, width: walletWidth, height: walletHeight) walletView.accountNameLabel.text = key accountSavingSubView.addSubview(walletView) // Update yPosition by adding the view's height, not maxY yPosition += walletHeight walletView.isUserInteractionEnabled = true print("walletView frame: \(walletView.frame)") } // Set contentSize to the final yPosition (total height of all wallets) self.contanerScrollView.contentSize = CGSize(width: walletWidth, height: yPosition) }
Extra Tips
- Call
createAndAddWallets()inviewDidLayoutSubviewsinstead ofviewDidLoad—this ensuresaccountSavingSubViewhas its final frame size when you create the Wallet views. - If your Wallet nib has internal AutoLayout constraints, stick with Option 1 to avoid layout conflicts and ensure better adaptability across screen sizes.
内容的提问来源于stack exchange,提问作者Gagan_iOS

