Swift 4中SwiftCharts横竖屏适配及旋转处理技术问询
Hey there! I’ve tackled these exact SwiftCharts layout headaches in Swift 4 before, so let’s break down how to fix both issues step by step.
The key here is to initialize your chart after the view has finished laying out its bounds for landscape orientation. viewDidLoad is too early because the view’s frame still uses portrait dimensions at that point. Instead, use viewDidLayoutSubviews:
First, make sure your view controller supports landscape orientation:
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { // Adjust based on your needs (e.g., .allButUpsideDown) return .landscape } override var shouldAutorotate: Bool { return true }
Then initialize your chart in viewDidLayoutSubviews to ensure you’re using the correct landscape bounds:
private var chart: Chart? override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // Avoid re-creating the chart every time the view lays out guard chart == nil else { return } // Sample data - replace with your own let sampleData = [ ChartDataPoint(x: 0, y: 4), ChartDataPoint(x: 1, y: 7), ChartDataPoint(x: 2, y: 2), ChartDataPoint(x: 3, y: 9) ] // Configure your chart axes let chartConfig = ChartConfig( xAxisConfig: ChartAxisConfig(from: 0, to: 3, by: 1), yAxisConfig: ChartAxisConfig(from: 0, to: 10, by: 2) ) // Create chart with the view's current landscape bounds let chartFrame = CGRect(origin: .zero, size: view.bounds.size) chart = Chart( frame: chartFrame, chartConfig: chartConfig, data: [sampleData], colors: [UIColor.systemBlue] ) view.addSubview(chart!) }
To make the chart adjust smoothly during rotation, you’ll need to update its frame and trigger a layout reload. The best place to do this is in viewWillTransition(to:with:):
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) // Animate the chart update alongside the rotation coordinator.animate(alongsideTransition: { _ in // Update the chart's frame to match the new screen size self.chart?.frame = CGRect(origin: .zero, size: size) // Tell SwiftCharts to reload its layout with the new dimensions self.chart?.reloadLayout() }, completion: nil) }
Bonus: Using AutoLayout for Even Smoother Adaptation
If you prefer AutoLayout over frame-based layout, you can pin the chart to your view’s edges. This way, the frame updates automatically during rotation, and you just need to trigger the layout reload:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() guard chart == nil else { return } // ... (keep your data and config setup the same) // Initialize with zero frame since we'll use constraints chart = Chart( frame: .zero, chartConfig: chartConfig, data: [sampleData], colors: [UIColor.systemBlue] ) chart?.translatesAutoresizingMaskIntoConstraints = false view.addSubview(chart!) // Pin chart to all edges of the view NSLayoutConstraint.activate([ chart!.leadingAnchor.constraint(equalTo: view.leadingAnchor), chart!.trailingAnchor.constraint(equalTo: view.trailingAnchor), chart!.topAnchor.constraint(equalTo: view.topAnchor), chart!.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) // Manually trigger initial layout chart?.reloadLayout() }
For rotation with AutoLayout, simplify the viewWillTransition method:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { _ in self.chart?.reloadLayout() }, completion: nil) }
A quick note: Always make sure you’re using a compatible version of SwiftCharts for Swift 4—some older versions might have layout quirks that are fixed in later releases.
内容的提问来源于stack exchange,提问作者Jon Clayton

