develop
UITableView UICollectionView Reorder 본문
Reorder기능은 셀을 터치한 다음 드래그로 셀의 위치를 바꾸는 기능이다.
UITableView Reorder
let tableView: UITableView = {
let tableView = UITableView()
return tableView
}()
var array: [UIColor] = [.blue, .red, .brown, .black, .green, .gray, .cyan, .orange, .darkGray, .lightGray, .link, .magenta, .purple, .yellow]
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.frame = self.view.frame
self.tableView.register(TableViewCell.self, forCellReuseIdentifier: TableViewCell.identifier)
self.tableView.rowHeight = 80
self.tableView.dataSource = self
self.tableView.reloadData()
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:)))
self.tableView.addGestureRecognizer(longPressGestureRecognizer)
}
@objc func longPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer) {
switch gestureRecognizer.state {
case .began:
case .changed:
case .ended, .cancelled, .failed, .possible:
default: break
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCell.identifier, for: indexPath) as? TableViewCell else { fatalError() }
cell.color = self.array[indexPath.row]
return cell
}
}
class TableViewCell: UITableViewCell {
static let identifier = "TableViewCell"
var color: UIColor? {
didSet {
self.colorView.backgroundColor = self.color
}
}
var isSnapshot: Bool? {
didSet {
self.colorView.isHidden = self.isSnapshot ?? false
}
}
var colorView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
self.contentView.addSubview(self.colorView)
self.contentView.addConstraints([
NSLayoutConstraint(item: self.contentView, attribute: .leading, relatedBy: .equal, toItem: self.colorView, attribute: .leading, multiplier: 1, constant: -10),
NSLayoutConstraint(item: self.contentView, attribute: .trailing, relatedBy: .equal, toItem: self.colorView, attribute: .trailing, multiplier: 1, constant: 10),
NSLayoutConstraint(item: self.contentView, attribute: .top, relatedBy: .equal, toItem: self.colorView, attribute: .top, multiplier: 1, constant: -10),
NSLayoutConstraint(item: self.contentView, attribute: .bottom, relatedBy: .equal, toItem: self.colorView, attribute: .bottom, multiplier: 1, constant: 10)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
간단하게 테이블 뷰를 만들고 셀에 넣을 UIColor 리스트를 만들었다.
그리고 추가적으로 테이블뷰에 UILongPressGestureRecognizer 를 추가하였다.
var gestureView: UIView? {
return self.view
}
var indexPath: IndexPath?
var touchPoint: CGPoint?
var snapshotView: UIView?
var prevSnapshotPoint: CGPoint?
제스쳐뷰는 Reorder기능이 동작할 뷰이다.
네비게이션이 상위에 있으면 네비게이션의 뷰, 탭이 가장 상위에 있으면 탭의 뷰를 넣는다.
indexPath는 터치, 드래그되고 있는 indexPath를 넣을것이고 touchPoint는 셀에 터치한 포인트를 넣을 것이다.
snapshotView는 터치, 드래그중 셀을 숨김처리 하고 대신 보여줄 뷰이다.
prevSnapshotPoint는 드래그중에 위로 드래그하는지 아래로 드래그하는지 체크할수 있는 좌표값이다.
func began(gestureRecognizer: UILongPressGestureRecognizer) {
let point = gestureRecognizer.location(in: self.tableView)
guard let indexPath = self.tableView.indexPathForRow(at: point),
let cell = self.tableView.cellForRow(at: indexPath) else { return }
self.indexPath = indexPath
if self.snapshotView == nil {
let imageView = UIImageView(image: cell.imageWithView)
imageView.layer.zPosition = 1024
self.gestureView?.addSubview(imageView)
self.snapshotView = imageView
}
let frame = cell.convert(cell.bounds, to: self.gestureView)
let scale: CGFloat = 1.05
let width = frame.size.width * scale
let height = frame.size.height * scale
let x = frame.origin.x - (width - frame.size.width)/2
let y = frame.origin.y - (height - frame.size.height)/2
self.snapshotView?.frame = CGRect(x: x, y: y, width: width, height: height)
self.prevSnapshotPoint = CGPoint(x: x, y: y)
if self.touchPoint == nil {
self.touchPoint = gestureRecognizer.location(in: cell)
}
(cell as? TableViewCell)?.isSnapshot = true
print("began: \(indexPath)")
}
extension UIView {
var imageWithView: UIImage {
let renderer = UIGraphicsImageRenderer(bounds: self.bounds)
return renderer.image { rendererContext in
self.layer.render(in: rendererContext.cgContext)
}
}
}
GestureRecognizer로 테이블뷰에서의 좌표를 가저온 다음 좌표를 통해 IndexPath를 가져온다.
그리고 snapshotView를 만들고 셀의 이미지를 넣어준다.
그리고 snapshotView를 사용자가 인지할수 있게 확대를 해준다.
다음 셀의 colorView를 숨겨준다.
func changed(gestureRecognizer: UILongPressGestureRecognizer) {
guard let touchPoint = self.touchPoint else { return }
guard let prevSnapshotPoint = self.prevSnapshotPoint else { return }
let gestureLocation = gestureRecognizer.location(in: self.gestureView)
let tableLocation = gestureRecognizer.location(in: self.tableView)
let gestureExactY = gestureLocation.y - touchPoint.y
let tableExactY = tableLocation.y - touchPoint.y
let isUp = prevSnapshotPoint.y - gestureExactY > 0
self.prevSnapshotPoint?.y = gestureExactY
self.snapshotView?.frame.origin.y = gestureExactY
let height = self.snapshotView?.bounds.height ?? 0
var indexPath: IndexPath?
if isUp {
if let minIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY + (height / 3))) {
indexPath = minIndexPath
} else if let maxIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY + height)) {
indexPath = maxIndexPath
}
} else {
if let minIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY + (height / 3 * 2))) {
indexPath = minIndexPath
} else if let maxIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY)) {
indexPath = maxIndexPath
}
}
if let beforeIndexPath = self.indexPath, let afterIndexPath = indexPath, beforeIndexPath != afterIndexPath {
self.array.swapAt(beforeIndexPath.row, afterIndexPath.row)
self.tableView.moveRow(at: beforeIndexPath, to: afterIndexPath)
(self.tableView.cellForRow(at: beforeIndexPath) as? TableViewCell)?.isSnapshot = false
(self.tableView.cellForRow(at: afterIndexPath) as? TableViewCell)?.isSnapshot = true
print("changed: beforeIndexPath-\(beforeIndexPath), afterIndexPath-\(afterIndexPath)")
self.indexPath = afterIndexPath
}
}
좌표를 계산하고 올라가는지 내려가는지를 체크해서 위, 또는 아래의 셀의 3분의 1지점에서 swap를 해준다.
func ended(gestureRecognizer: UILongPressGestureRecognizer) {
if let indexPath = self.indexPath {
(self.tableView.cellForRow(at: indexPath) as? TableViewCell)?.isSnapshot = false
}
self.snapshotView?.removeFromSuperview()
self.snapshotView = nil
self.touchPoint = nil
self.prevSnapshotPoint = nil
self.indexPath = nil
print("end")
}
snapshotView를 지우고 숨겼던 셀을 보여준다.
UITableView Reorder 전체 코드
class ViewController: UIViewController {
let tableView: UITableView = {
let tableView = UITableView()
return tableView
}()
var array: [UIColor] = [.blue, .red, .brown, .black, .green, .gray, .cyan, .orange, .darkGray, .lightGray, .link, .magenta, .purple, .yellow]
var gestureView: UIView? {
return self.view
}
var indexPath: IndexPath?
var touchPoint: CGPoint?
var snapshotView: UIView?
var prevSnapshotPoint: CGPoint?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.tableView)
self.tableView.frame = self.view.frame
self.tableView.register(TableViewCell.self, forCellReuseIdentifier: TableViewCell.identifier)
self.tableView.rowHeight = 80
self.tableView.dataSource = self
self.tableView.reloadData()
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:)))
self.tableView.addGestureRecognizer(longPressGestureRecognizer)
}
@objc func longPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer) {
switch gestureRecognizer.state {
case .began:
self.began(gestureRecognizer: gestureRecognizer)
case .changed:
self.changed(gestureRecognizer: gestureRecognizer)
case .ended, .cancelled, .failed, .possible:
self.ended(gestureRecognizer: gestureRecognizer)
default: break
}
}
func began(gestureRecognizer: UILongPressGestureRecognizer) {
let point = gestureRecognizer.location(in: self.tableView)
guard let indexPath = self.tableView.indexPathForRow(at: point),
let cell = self.tableView.cellForRow(at: indexPath) else { return }
self.indexPath = indexPath
if self.snapshotView == nil {
let imageView = UIImageView(image: cell.imageWithView)
imageView.layer.zPosition = 1024
self.gestureView?.addSubview(imageView)
self.snapshotView = imageView
}
let frame = cell.convert(cell.bounds, to: self.gestureView)
let scale: CGFloat = 1.05
let width = frame.size.width * scale
let height = frame.size.height * scale
let x = frame.origin.x - (width - frame.size.width)/2
let y = frame.origin.y - (height - frame.size.height)/2
self.snapshotView?.frame = CGRect(x: x, y: y, width: width, height: height)
self.prevSnapshotPoint = CGPoint(x: x, y: y)
if self.touchPoint == nil {
self.touchPoint = gestureRecognizer.location(in: cell)
}
(cell as? TableViewCell)?.isSnapshot = true
print("began: \(indexPath)")
}
func changed(gestureRecognizer: UILongPressGestureRecognizer) {
guard let touchPoint = self.touchPoint else { return }
guard let prevSnapshotPoint = self.prevSnapshotPoint else { return }
let gestureLocation = gestureRecognizer.location(in: self.gestureView)
let tableLocation = gestureRecognizer.location(in: self.tableView)
let gestureExactY = gestureLocation.y - touchPoint.y
let tableExactY = tableLocation.y - touchPoint.y
let isUp = prevSnapshotPoint.y - gestureExactY > 0
self.prevSnapshotPoint?.y = gestureExactY
self.snapshotView?.frame.origin.y = gestureExactY
let height = self.snapshotView?.bounds.height ?? 0
var indexPath: IndexPath?
if isUp {
if let minIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY + (height / 3))) {
indexPath = minIndexPath
} else if let maxIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY + height)) {
indexPath = maxIndexPath
}
} else {
if let minIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY + (height / 3 * 2))) {
indexPath = minIndexPath
} else if let maxIndexPath = self.tableView.indexPathForRow(at: CGPoint(x: 10, y: tableExactY)) {
indexPath = maxIndexPath
}
}
if let beforeIndexPath = self.indexPath, let afterIndexPath = indexPath, beforeIndexPath != afterIndexPath {
self.array.swapAt(beforeIndexPath.row, afterIndexPath.row)
self.tableView.moveRow(at: beforeIndexPath, to: afterIndexPath)
(self.tableView.cellForRow(at: beforeIndexPath) as? TableViewCell)?.isSnapshot = false
(self.tableView.cellForRow(at: afterIndexPath) as? TableViewCell)?.isSnapshot = true
print("changed: beforeIndexPath-\(beforeIndexPath), afterIndexPath-\(afterIndexPath)")
self.indexPath = afterIndexPath
}
}
func ended(gestureRecognizer: UILongPressGestureRecognizer) {
if let indexPath = self.indexPath {
(self.tableView.cellForRow(at: indexPath) as? TableViewCell)?.isSnapshot = false
}
self.snapshotView?.removeFromSuperview()
self.snapshotView = nil
self.touchPoint = nil
self.prevSnapshotPoint = nil
self.indexPath = nil
print("end")
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCell.identifier, for: indexPath) as? TableViewCell else { fatalError() }
cell.color = self.array[indexPath.row]
return cell
}
}
class TableViewCell: UITableViewCell {
static let identifier = "TableViewCell"
var color: UIColor? {
didSet {
self.colorView.backgroundColor = self.color
}
}
var isSnapshot: Bool? {
didSet {
self.colorView.isHidden = self.isSnapshot ?? false
}
}
var colorView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
self.contentView.addSubview(self.colorView)
self.contentView.addConstraints([
NSLayoutConstraint(item: self.contentView, attribute: .leading, relatedBy: .equal, toItem: self.colorView, attribute: .leading, multiplier: 1, constant: -10),
NSLayoutConstraint(item: self.contentView, attribute: .trailing, relatedBy: .equal, toItem: self.colorView, attribute: .trailing, multiplier: 1, constant: 10),
NSLayoutConstraint(item: self.contentView, attribute: .top, relatedBy: .equal, toItem: self.colorView, attribute: .top, multiplier: 1, constant: -10),
NSLayoutConstraint(item: self.contentView, attribute: .bottom, relatedBy: .equal, toItem: self.colorView, attribute: .bottom, multiplier: 1, constant: 10)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIView {
var imageWithView: UIImage {
let renderer = UIGraphicsImageRenderer(bounds: self.bounds)
return renderer.image { rendererContext in
self.layer.render(in: rendererContext.cgContext)
}
}
}
UICollectionView Reorder
UICollectionView의 Reorder는 UITableView의 Reorder과 크게 다른점이 없다.
UICollectionView의 메서드 이름들이 달라진다.
그리고 UICollectionView는 Y좌표 뿐만 아니라 X좌표도 변하게 된다.
X좌표를 추가적으로 계산해서 구현해준다.
let minY = isUp ? viewExactPoint.y + (height / 3) : viewExactPoint.y + (height / 3 * 2)
let maxY = isUp ? viewExactPoint.y + height : viewExactPoint.y
let minX = isLeft ? viewExactPoint.x + (width / 3) : viewExactPoint.x + (width / 3 * 2)
let maxX = isLeft ? viewExactPoint.x + width : viewExactPoint.x
if let minIndexPath = self.collectionView.indexPathForItem(at: CGPoint(x: minX, y: minY)) {
indexPath = minIndexPath
} else if let maxIndexPath = self.collectionView.indexPathForItem(at: CGPoint(x: maxX, y: maxY)) {
indexPath = maxIndexPath
}
그리고 moveItem 또는 moveRow와 array의 swap함수가 로직적으로 다르다.
테이블뷰에서는 moveRow와 array의 swap이 한칸한칸 바뀌는 거라 동일하게 작동하지만
콜렉션뷰에서는 y좌표를 움직일때 moveItem 은 동일 x좌표에 있는 셀들의 index가 변하게 된다.
let beforeItem = self.array.remove(at: beforeIndexPath.row)
self.array.insert(beforeItem, at: afterIndexPath.row)
self.collectionView.moveItem(at: beforeIndexPath, to: afterIndexPath)
(self.collectionView.cellForItem(at: beforeIndexPath) as? CollectionViewCell)?.isSnapshot = false
(self.collectionView.cellForItem(at: afterIndexPath) as? CollectionViewCell)?.isSnapshot = true
print("changed: beforeIndexPath-\(beforeIndexPath), afterIndexPath-\(afterIndexPath)")
self.indexPath = afterIndexPath
이 두가지 외에는 UITableView와 UICollectionView의 기본적인 메서드, 변수명만 변한다.
UICollectionView Reorder 전체 코드
class ViewController: UIViewController {
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: (UIScreen.main.bounds.width/3) - 20, height: 80)
layout.minimumLineSpacing = 10
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .white
return collectionView
}()
var array: [UIColor] = [.blue, .red, .brown, .black, .green, .gray, .cyan, .orange, .darkGray, .lightGray, .link, .magenta, .purple, .yellow, UIColor(white: 99/255, alpha: 1), UIColor(white: 44/255, alpha: 1), UIColor(white: 124/255, alpha: 1), UIColor(white: 180/255, alpha: 1)]
var gestureView: UIView? {
return self.view
}
var indexPath: IndexPath?
var touchPoint: CGPoint?
var snapshotView: UIView?
var prevSnapshotPoint: CGPoint?
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.collectionView)
self.collectionView.frame = self.view.frame
self.collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: CollectionViewCell.identifier)
self.collectionView.dataSource = self
self.collectionView.reloadData()
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:)))
self.collectionView.addGestureRecognizer(longPressGestureRecognizer)
}
@objc func longPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer) {
switch gestureRecognizer.state {
case .began:
self.began(gestureRecognizer: gestureRecognizer)
case .changed:
self.changed(gestureRecognizer: gestureRecognizer)
case .ended, .cancelled, .failed, .possible:
self.ended(gestureRecognizer: gestureRecognizer)
default: break
}
}
func began(gestureRecognizer: UILongPressGestureRecognizer) {
let point = gestureRecognizer.location(in: self.collectionView)
guard let indexPath = self.collectionView.indexPathForItem(at: point),
let cell = self.collectionView.cellForItem(at: indexPath) else { return }
self.indexPath = indexPath
if self.snapshotView == nil {
let imageView = UIImageView(image: cell.imageWithView)
imageView.layer.zPosition = 1024
self.gestureView?.addSubview(imageView)
self.snapshotView = imageView
}
let frame = cell.convert(cell.bounds, to: self.gestureView)
let scale: CGFloat = 1.05
let width = frame.size.width * scale
let height = frame.size.height * scale
let x = frame.origin.x - (width - frame.size.width)/2
let y = frame.origin.y - (height - frame.size.height)/2
self.snapshotView?.frame = CGRect(x: x, y: y, width: width, height: height)
self.prevSnapshotPoint = CGPoint(x: x, y: y)
if self.touchPoint == nil {
self.touchPoint = gestureRecognizer.location(in: cell)
}
(cell as? CollectionViewCell)?.isSnapshot = true
print("began: \(indexPath)")
}
func changed(gestureRecognizer: UILongPressGestureRecognizer) {
guard let touchPoint = self.touchPoint else { return }
guard let prevSnapshotPoint = self.prevSnapshotPoint else { return }
let gestureLocation = gestureRecognizer.location(in: self.gestureView)
let viewLocation = gestureRecognizer.location(in: self.collectionView)
let gestureExactPoint = CGPoint(x: gestureLocation.x - touchPoint.x, y: gestureLocation.y - touchPoint.y)
let viewExactPoint = CGPoint(x: viewLocation.x - touchPoint.x, y: viewLocation.y - touchPoint.y)
let isUp = prevSnapshotPoint.y - gestureExactPoint.y > 0
let isLeft = prevSnapshotPoint.x - gestureExactPoint.x > 0
self.prevSnapshotPoint?.x = gestureExactPoint.x
self.prevSnapshotPoint?.y = gestureExactPoint.y
self.snapshotView?.frame.origin.x = gestureExactPoint.x
self.snapshotView?.frame.origin.y = gestureExactPoint.y
let width = self.snapshotView?.bounds.width ?? 0
let height = self.snapshotView?.bounds.height ?? 0
var indexPath: IndexPath?
let minY = isUp ? viewExactPoint.y + (height / 3) : viewExactPoint.y + (height / 3 * 2)
let maxY = isUp ? viewExactPoint.y + height : viewExactPoint.y
let minX = isLeft ? viewExactPoint.x + (width / 3) : viewExactPoint.x + (width / 3 * 2)
let maxX = isLeft ? viewExactPoint.x + width : viewExactPoint.x
if let minIndexPath = self.collectionView.indexPathForItem(at: CGPoint(x: minX, y: minY)) {
indexPath = minIndexPath
} else if let maxIndexPath = self.collectionView.indexPathForItem(at: CGPoint(x: maxX, y: maxY)) {
indexPath = maxIndexPath
}
if let beforeIndexPath = self.indexPath, let afterIndexPath = indexPath, beforeIndexPath != afterIndexPath {
let beforeItem = self.array.remove(at: beforeIndexPath.row)
self.array.insert(beforeItem, at: afterIndexPath.row)
self.collectionView.moveItem(at: beforeIndexPath, to: afterIndexPath)
(self.collectionView.cellForItem(at: beforeIndexPath) as? CollectionViewCell)?.isSnapshot = false
(self.collectionView.cellForItem(at: afterIndexPath) as? CollectionViewCell)?.isSnapshot = true
print("changed: beforeIndexPath-\(beforeIndexPath), afterIndexPath-\(afterIndexPath)")
self.indexPath = afterIndexPath
}
}
func ended(gestureRecognizer: UILongPressGestureRecognizer) {
if let indexPath = self.indexPath {
(self.collectionView.cellForItem(at: indexPath) as? CollectionViewCell)?.isSnapshot = false
}
self.snapshotView?.removeFromSuperview()
self.snapshotView = nil
self.touchPoint = nil
self.prevSnapshotPoint = nil
self.indexPath = nil
print("end")
}
}
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.identifier, for: indexPath) as? CollectionViewCell else { fatalError() }
cell.color = self.array[indexPath.row]
return cell
}
}
class CollectionViewCell: UICollectionViewCell {
static let identifier = "CollectionViewCell"
var color: UIColor? {
didSet {
self.colorView.backgroundColor = self.color
}
}
var isSnapshot: Bool? {
didSet {
self.colorView.isHidden = self.isSnapshot ?? false
}
}
var colorView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.addSubview(self.colorView)
self.contentView.addConstraints([
NSLayoutConstraint(item: self.contentView, attribute: .leading, relatedBy: .equal, toItem: self.colorView, attribute: .leading, multiplier: 1, constant: 0),
NSLayoutConstraint(item: self.contentView, attribute: .trailing, relatedBy: .equal, toItem: self.colorView, attribute: .trailing, multiplier: 1, constant: 0),
NSLayoutConstraint(item: self.contentView, attribute: .top, relatedBy: .equal, toItem: self.colorView, attribute: .top, multiplier: 1, constant: 0),
NSLayoutConstraint(item: self.contentView, attribute: .bottom, relatedBy: .equal, toItem: self.colorView, attribute: .bottom, multiplier: 1, constant: 0)
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIView {
var imageWithView: UIImage {
let renderer = UIGraphicsImageRenderer(bounds: self.bounds)
return renderer.image { rendererContext in
self.layer.render(in: rendererContext.cgContext)
}
}
}
'iOS' 카테고리의 다른 글
==과 ===의 차이, closure의 === (0) | 2021.06.22 |
---|---|
iOS에서 srt, smi 파일 한글 깨지는 문제 (0) | 2021.03.01 |
GCD (0) | 2021.02.06 |
OperationQueue (0) | 2021.02.05 |
Thread (0) | 2021.02.04 |