이번에 도서추천 어플을 개발하면서 새롭게 알았던 것들이나 유용하게 쓰였던 코드를 정리해보려고 한다!
extension UIColor {
convenience init(hexCode: String, alpha: CGFloat = 1.0) {
var hexFormatted: String = hexCode.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).uppercased()
if hexFormatted.hasPrefix("#") {
hexFormatted = String(hexFormatted.dropFirst())
}
assert(hexFormatted.count == 6, "Invalid hex code used.")
var rgbValue: UInt64 = 0
Scanner(string: hexFormatted).scanHexInt64(&rgbValue)
self.init(red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
alpha: alpha)
}
}
class ExtensionVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension UIViewController {
class func displaySpinner(onView: UIView) -> UIView {
let spinnerView = UIView.init(frame: onView.bounds)
spinnerView.backgroundColor = .white
let ai = UIActivityIndicatorView.init(style: .medium)
ai.startAnimating()
ai.center = spinnerView.center
DispatchQueue.main.async {
spinnerView.addSubview(ai)
onView.addSubview(spinnerView)
}
return spinnerView
}
class func removeSpinner(spinner : UIView) {
DispatchQueue.main.async {
spinner.removeFromSuperview()
}
}
}
로딩화면을 사용할 ViewController에서 UIViewController대신, 위에 생성한 ExtensionVC를 상속받는다.
UIView 변수 선언
weak var sv: UIView!
func showIndicator(){
DispatchQueue.main.async {
self.sv = UIViewController.displaySpinner(onView: self.view)
}
}
func hideIndicator(){
DispatchQueue.main.async {
self.sv?.removeFromSuperview()
}
}
class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes = super.layoutAttributesForElements(in: rect)
var leftMargin = sectionInset.left
var maxY: CGFloat = -1.0
attributes?.forEach { layoutAttribute in
if layoutAttribute.representedElementKind == nil {
if layoutAttribute.frame.origin.y >= maxY {
leftMargin = sectionInset.left
}
layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
maxY = max(layoutAttribute.frame.maxY, maxY)
}
}
return attributes
}
}
func setupCollectionView(){
let layout = LeftAlignedCollectionViewFlowLayout()
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 10
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
recKeywordCollectionView.dataSource = self
recKeywordCollectionView.collectionViewLayout = layout
}
public class VerticalAlignLabel: UILabel {
enum VerticalAlignment {
case top
case middle
case bottom
}
var verticalAlignment : VerticalAlignment = .top {
didSet {
setNeedsDisplay()
}
}
override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft {
switch verticalAlignment {
case .top:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
} else {
switch verticalAlignment {
case .top:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
}
}
override public func drawText(in rect: CGRect) {
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
}
}
@IBOutlet weak var descriptionLabel: VerticalAlignLabel!
descriptionLabel.verticalAlignment = .top