-
Swift(UIKit) 를 SwiftUI처럼 쓰는 방법SwiftUI 2021. 12. 24. 13:28
1. Builder Pattern 사용
: 명명을 Worker로 변경(Ribs에서 Builder 가 충돌나기 때문)
dynamicMemberLookup에 대한 상세 설명 및 출처 : https://kkimin.tistory.com/83
import UIKit @dynamicMemberLookup struct Worker<Base: AnyObject> { private var base: Base init(_ base: Base) { self.base = base } subscript<Value>(dynamicMember keyPath: ReferenceWritableKeyPath<Base, Value>) -> (Value) -> Worker<Base> { { [base] value in base[keyPath: keyPath] = value return Worker(base) } } @discardableResult func build() -> Base { return base } } extension Worker where Base: UIView { @discardableResult func add(to view: UIView, constraints: (Base) -> [NSLayoutConstraint]) -> Base { return add(to: view) .activate(constraints) .build() } @discardableResult func add(to view: UIView) -> Worker<Base> { base.addSubview(view) return self } @discardableResult func activate(_ constraints: (Base) -> [NSLayoutConstraint]) -> Worker<Base> { base.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate(constraints(base)) return self } @discardableResult func background(color: UIColor) -> Worker<Base> { base.backgroundColor = color return self } func borderRadius(_ r: CGFloat) -> Worker<Base> { base.layer.cornerRadius = r base.clipsToBounds = true return self } } protocol Workable: AnyObject {} extension Workable { var builder: Worker<Self> { Worker(self) } } extension NSObject: Workable {} extension Worker where Base: UILabel { func text(_ text: String) -> Worker<Base> { base.text = text return self } func numberOfLines(_ lines: Int = 0) -> Worker<Base> { base.numberOfLines = lines return self } } extension Worker where Base: UIButton { func addImage(_ image: UIImage = .add) -> Worker<Base> { base.setImage(image, for: .normal) return self } } } // 이런식으로 많은 확장 가능.
사실 위처럼 하지 않고, UI를 생성할때 아래 같은 식으로 작성해도 되지만 위처럼 하면 더 많은 커스텀이 가능하다.
// 이런식으로도 가능하지만 private lazy var tableView: UITableView = { let tableView = UITableView() tableView.translatesAutoresizingMaskIntoConstraints = false tableView.delegate = self tableView.register(cellType: CustomCell.self) tableView.rowHeight = 100 return tableView }() // builder를 쓰면 아래처럼 작성 가능 (기능들은 더 확장으로 추가되어야함) private lazy var testView = UITableView().builder .translatesAutoresizingMaskIntoConstraints(false) .build()
++ Then 도 비슷한 형식으로 추가
public protocol Then {} extension NSObject: Then {} extension Then where Self: AnyObject { public func then(_ block: (Self) throws -> Void) rethrows -> Self { try block(self) return self }
2. UIPreviewProvider 사용하기
Preview 사용 조건
- Xcode 11 이상
- macOS Catalina 이상
- iOS 13+
enum DeviceType { case iPhoneSE2 case iPhone8 case iPhone12Pro case iPhone12ProMax func name() -> String { switch self { case .iPhoneSE2: return "iPhone SE" case .iPhone8: return "iPhone 8" case .iPhone12Pro: return "iPhone 12 Pro" case .iPhone12ProMax: return "iPhone 12 Pro Max" } } } #if canImport(SwiftUI) import SwiftUI extension UIViewController { private struct Preview: UIViewControllerRepresentable { let viewController: UIViewController func makeUIViewController(context: Context) -> UIViewController { return viewController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { } } func showPreview(_ deviceType: DeviceType = .iPhone12Pro) -> some View { Preview(viewController: self).previewDevice(PreviewDevice(rawValue: deviceType.name())) } } #endif
이렇게 선언해 두고
실제로 보고싶은 ViewController 를 아래처럼 실행시킨다. - 아래 따로 작성 (당연히 View로도 가능)
#if canImport(SwiftUI) import SwiftUI struct VCPreView: PreviewProvider { static var previews: some View { ViewController().showPreview(.iPhone8) } } #endif
만약?
이렇게 했는데 자동으로 preview가 나오지 않는다?
To open the preview canvas, just go to Editor -> Canvas
Or do Alt + Command + Enter
하면 나올거다.
이렇게 하면 상황별로 보기도 좋고, 또 코드로 view를 짠 경우 확인에도 좋다. 대충 아래처럼 미리 나오는거다!! - 확장성 및 기능도 다양함!!
출처 및 참고 : https://ios-development.tistory.com/488, https://fluffy.es/xcode-previews-uikit/
728x90