structBarChartModel{varpercentage:CGFloatvarvalue:Intvarname:Stringvarcolor:UIColor}classViewController:UIViewController{vardataSource=[(7,"太郎"),(1,"次郎"),(2,"三郎"),(6,"四郎"),(3,"五郎"),(9,"六郎"),(2,"七郎"),(3,"八郎"),(1,"九郎"),(5,"十郎"),(1,"十一郎"),(1,"十二郎"),(6,"十三郎")]lazyvardata:[[BarChartModel]]=format(dataSource)lazyvarmaxVal:Int=dataSource.map({$0.0}).max()??-1@IBOutletweakvarscrollView:UIScrollView!overridefuncviewDidLoad(){super.viewDidLoad()// Do any additional setup after loading the view.scrollView.frame=CGRect(x:0,y:0,width:scrollView.superview!.frame.width,height:scrollView.superview!.frame.height)configureScrollView()}privatefuncconfigureScrollView(){scrollView.isPagingEnabled=trueletcontentsView=UIView(frame:CGRect(x:0,y:0,width:scrollView.frame.width*CGFloat(data.count),height:scrollView.frame.height))scrollView.addSubview(contentsView)scrollView.contentSize=contentsView.frame.sizefor(i,barChartItems)indata.enumerated(){letwidthPercentage=CGFloat(barChartItems.count)/CGFloat(data[0].count)letframe=CGRect(x:scrollView.frame.width*CGFloat(i),y:0,width:scrollView.frame.width*widthPercentage,height:scrollView.frame.height)letview=BarChartView(frame:frame,barChartItems:barChartItems)contentsView.addSubview(view)}}privatefuncformat(_data:[(Int,String)])->[[BarChartModel]]{returndata.map({datuminlet(val,name)=datumletpercentage=CGFloat(val)/CGFloat(maxVal)letcolor:UIColor=val==maxVal?.systemOrange:.systemBluereturnBarChartModel(percentage:percentage,value:val,name:name,color:color)}).chunked(into:5)}}extensionArray{funcchunked(intosize:Int)->[[Element]]{returnstride(from:0,to:count,by:size).map{Array(self[$0..<Swift.min($0+size,count)])}}}
classBarChartView:UIStackView{letfontSize:CGFloat=20lettextPad:CGFloat=10init(frame:CGRect,barChartItems:[BarChartModel]){super.init(frame:frame)axis=.horizontaldistribution=.fillEquallyalignment=.bottomspacing=20isLayoutMarginsRelativeArrangement=truelayoutMargins.left=20layoutMargins.right=20foriteminbarChartItems{addBarContainer(of:item)}drawBorderBottom()}requiredinit(coder:NSCoder){fatalError("init(coder:) has not been implemented")}privatefuncaddBarContainer(ofitem:BarChartModel){letvalueLabelHeight=fontSize+textPadletnameLabelHeight=fontSize+textPadletbarHeight=(frame.height-valueLabelHeight-nameLabelHeight)*item.percentageletbarContainerView=BarContainerView(item:item,barHeight:barHeight,valueLabelHeight:fontSize+textPad,nameLabelHeight:fontSize+textPad,fontSize:fontSize)addArrangedSubview(barContainerView)}privatefuncdrawBorderBottom(){letborder=CALayer()letborderWidth:CGFloat=1border.backgroundColor=UIColor.darkGray.cgColorborder.frame=CGRect(x:0,y:frame.height-(borderWidth/2+fontSize+textPad),width:frame.width,height:borderWidth)layer.addSublayer(border)}}
classBarContainerView:UIStackView{varbarView:UIView!varvalueLabel:UILabel!varnameLabel:UILabel!letitem:BarChartModelvarbarViewHeightConstraint:NSLayoutConstraint!init(item:BarChartModel,barHeight:CGFloat,valueLabelHeight:CGFloat,nameLabelHeight:CGFloat,fontSize:CGFloat){self.item=itemsuper.init(frame:CGRect.zero)axis=.verticalalignment=.filldistribution=.fillvalueLabel=makeBarLabel(text:"\(item.value)",fontSize:fontSize,height:valueLabelHeight)addArrangedSubview(valueLabel)barView=makeBar(barHeight:barHeight)addArrangedSubview(barView)nameLabel=makeBarLabel(text:item.name,fontSize:fontSize,height:nameLabelHeight)addArrangedSubview(nameLabel)}requiredinit(coder:NSCoder){fatalError("init(coder:) has not been implemented")}privatefuncmakeBar(barHeight:CGFloat)->UIView{letbarView=UIView()barView.backgroundColor=item.colorbarView.translatesAutoresizingMaskIntoConstraints=falsebarViewHeightConstraint=barView.heightAnchor.constraint(equalToConstant:barHeight)barViewHeightConstraint.isActive=truereturnbarView}privatefuncmakeBarLabel(text:String,fontSize:CGFloat,height:CGFloat)->UILabel{letlabel=UILabel()label.font=.systemFont(ofSize:fontSize)label.textColor=.graylabel.text=textlabel.textAlignment=.centerlabel.adjustsFontSizeToFitWidth=truelabel.translatesAutoresizingMaskIntoConstraints=falselabel.heightAnchor.constraint(equalToConstant:height).isActive=truereturnlabel}}
classDetailViewController:UIViewController{@IBOutletweakvarnameLabel:UILabel!@IBOutletweakvarvalueLabel:UILabel!varitem:BarChartModel!overridefuncviewDidLoad(){super.viewDidLoad()// Do any additional setup after loading the view.nameLabel.text=item.namevalueLabel.text="\(item.value)"}}