控制器
import UIKit
class AutoSizingViewController: UIViewController {
// 自定义视图
private var mainView: AutoSizingView {
return self.view as! AutoSizingView
}
// 将自定义视图赋值给控制器的view
override func loadView() {
self.view = AutoSizingView()
}
override func viewDidLoad() {
super.viewDidLoad()
configureNavigationBar()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
randomizeContent()
}
private func configureNavigationBar() {
navigationItem.title = "AutoSizing"
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Randomize", style: .plain, target: self, action: #selector(randomizeContent))
}
@objc
private func randomizeContent() {
// 网络请求给视图的属性赋值【mainView】
ContentService.shared.fetchText(numberOfParagraph: 2) { [weak self] (result) in
guard let strongSelf = self, case let .success(paragraphs) = result else { return }
strongSelf.mainView.updateTexts(firstText: paragraphs[0], secondText: paragraphs[1])
}
ContentService.shared.fetchImage(width: Int.random(in: 200..<500), height: Int.random(in: 200..<500)) { [weak self] (result) in
guard let strongSelf = self, case let .success(image) = result else { return }
strongSelf.mainView.updateImage(image)
}
}
}
自定义视图
AutoSizingView
import UIKit
import PinLayout
final class AutoSizingView: UIView {
private let scrollView = UIScrollView()
private let containerView = AutoSizingContainerView()
private let margin: CGFloat = 30
init() {
super.init(frame: CGRect.zero)
configureView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configureView() {
backgroundColor = .white
scrollView.alwaysBounceVertical = true
addSubview(scrollView)
containerView.backgroundColor = UIColor.lightGray.withAlphaComponent(0.3)
scrollView.addSubview(containerView)
}
func updateImage(_ image: UIImage?) {
containerView.image = image
setNeedsLayout()
}
func updateTexts(firstText: String?, secondText: String?) {
containerView.firstText = firstText
containerView.secondText = secondText
setNeedsLayout()
}
override func layoutSubviews() {
super.layoutSubviews()
performLayout()
didPerformLayout()
}
private func performLayout() {
scrollView.pin.all()
containerView.pin.top(margin).horizontally(margin).sizeToFit(.width)
}
private func didPerformLayout() {
scrollView.contentSize = CGSize(width: bounds.width, height: containerView.frame.maxY + margin)
}
}
AutoSizingContainerView
import UIKit
final class AutoSizingContainerView: UIView {
private let imageView = UIImageView()
private let firstTextLabel = UILabel()
private let secondTextLabel = UILabel()
private let margin: CGFloat = 10
var image: UIImage? {
didSet {
imageView.image = image
}
}
var firstText: String? {
didSet {
firstTextLabel.text = firstText
}
}
var secondText: String? {
didSet {
secondTextLabel.text = secondText
}
}
init() {
super.init(frame: CGRect.zero)
configureView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configureView() {
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
addSubview(imageView)
firstTextLabel.numberOfLines = 0
firstTextLabel.backgroundColor = UIColor.orange.withAlphaComponent(0.3)
addSubview(firstTextLabel)
secondTextLabel.numberOfLines = 0
secondTextLabel.backgroundColor = UIColor.green.withAlphaComponent(0.3)
addSubview(secondTextLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
performLayout()
}
private func performLayout() {
imageView.pin.top().horizontally().sizeToFit(.width).margin(margin)
firstTextLabel.pin.below(of: imageView).horizontally().sizeToFit(.width).margin(margin)
secondTextLabel.pin.below(of: firstTextLabel).horizontally().sizeToFit(.width).margin(margin)
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
autoSizeThatFits(size, layoutClosure: performLayout)
}
}