Live Preview功用能让咱们在开发过程中实时看到UI层面的改动作用,不用每次稍有改动就得运转整个APP,并且跳转到对应的页面才干看到实际作用,这必然会极大的提高开发功率。SwiftUIPreview是为SwiftUI规划的,但是在UIKit环境下也可以运用,本文针对这个场景的实践做一个记录。
新建一个swift项目,删去Storyboard
在info.plist中删去
<key>UISceneStoryboardFile</key>
<string>Main</string>
在SceneDelegate中,设置window的根控制器
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
let vc = ViewController()
let nav = UINavigationController(rootViewController: vc)
window.rootViewController = nav
window.makeKeyAndVisible()
self.window = window
给UIView和UIViewController 增加 Preview的extension
创立UIViewControllerExtension.swift文件
import UIKit
import SwiftUI
extension UIViewController {
@available(iOS 13, *)
private struct Preview: UIViewControllerRepresentable {
// 用于注入当前的viewcontroller
let viewController: UIViewController
func makeUIViewController(context: Context) -> UIViewController {
return viewController
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
//
}
}
@available(iOS 13, *)
func showPreview() -> some View {
Preview(viewController: self)
}
}
创立UIViewExtension.swift
import UIKit
import SwiftUI
extension UIView {preview-uikit-views-in-xcode-3543
@available(iOS 13, *)
private struct Preview: UIViewRepresentable {
typealias UIViewType = UIView
let view: UIView
func makeUIView(context: Context) -> UIView {
return view
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
@available(iOS 13, *)
func showPreview() -> some View {
// inject self (the current UIView) for the preview
Preview(view: self)
}
}
具体运用?
新建一个用户信息的view,增加imageview、和两个label,约束用的是SnapKit
import UIKit
import SnapKit
class UserInfo: UIView{
override init(frame: CGRect) {
super.init(frame: frame)
setUpView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpView()
}
lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "我的信息"
label.font = .boldSystemFont(ofSize: 24)
label.textAlignment = .left
return label
}()
let imageWidth = 60.0
lazy var profileImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "yaofan"))
imageView.clipsToBounds = true
imageView.layer.cornerRadius = imageWidth / 2
imageView.layer.borderWidth = 1
imageView.layer.borderColor = UIColor.black.withAlphaComponent(0.1).cgColor
return imageView
}()
lazy var nameLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 18)
label.text = "Luseike"
return label
}()
lazy var roleLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 15)
label.textColor = .gray
label.text = "iOS Engineer"
return label
}()
lazy var nameStackView: UIStackView = {
let stack = UIStackView(arrangedSubviews: [nameLabel, roleLabel])
stack.axis = .vertical
stack.alignment = .leading
stack.spacing = 4
return stack
}()
func setUpView(){
self.addSubview(titleLabel)
self.addSubview(profileImageView)
self.addSubview(nameStackView)
titleLabel.snp.makeConstraints { make in
make.top.equalTo(self.safeAreaLayoutGuide.snp.top).offset(10)
make.leading.trailing.equalToSuperview().inset(24)
}
profileImageView.snp.makeConstraints { make in
make.width.height.equalTo(imageWidth)
make.top.equalTo(titleLabel.snp.bottom).offset(16)
make.leading.equalToSuperview().offset(20)
}
nameStackView.snp.makeConstraints { make in
make.leading.equalTo(profileImageView.snp.trailing).offset(12)
make.centerY.equalTo(profileImageView.snp.centerY)
make.trailing.equalToSuperview().offset(-20)
}
}
}
在view底部,增加一个承继PreviewProvider的struct,由于上面现已增加了UIView的扩展,会call到showPreview()使其有能力来preview咱们自定义的view
#if DEBUG
import SwiftUI
@available(iOS 13, *)
struct HeaderView_Preview: PreviewProvider {
static var previews: some View {
HeaderView().showPreview()
}
}
#endif
controller文件的preview运用跟view是相似的
#if DEBUG
import SwiftUI
@available(iOS 13, *)
struct ViewController_Preview: PreviewProvider {
static var previews: some View {
ViewController().showPreview()
}
}
#endif