在UIkit框架中嵌套部分swiftUI之UIViewController中添加SwiftUI視圖
系統(tǒng)適配最低版本:iOS13
將swiftUI視圖添加至UIViewController中
1.需要使用UIHostingController
2.計算出swiftUI視圖的尺寸
3.如果有導航欄隱藏,注意處理
代碼:
@discardableResult
func addSwiftUIView<Content: View>(_ rhs: Content) -> UIHostingController<Content> {
let vc = UIHostingController(rootView: rhs)
vc.view.backgroundColor = .clear
vc.edgesForExtendedLayout = []
self.addChild(vc)
self.view.addSubview(vc.view)
// vc.view.sizeToFit()
printLog("之前計算出來的size = \(vc.view.frame.size)")
/// 使用該方法 計算swiftUI部分的高度碍岔,便于在UIKit中進行布局
let targetSize = CGSize(width: view.bounds.width, height: UIView.layoutFittingCompressedSize.height)
let size = vc.sizeThatFits(in: targetSize)
printLog("計算出來的size = \(size)")
vc.view.frame.size = size
vc.view.translatesAutoresizingMaskIntoConstraints = false
self.navigationController?.setNavigationBarHidden(true, animated: false)
vc.didMove(toParent: self)
return vc
}
登錄頁面其他登錄方式部分的SwiftUI實現(xiàn)代碼
1.同樣需要注意如果導航欄隱藏需要進行處理
2.iOS13上浴讯,給Button設置圖片時,注意渲染模式
struct AppLoginWayView: View {
var wayAction: (AppLogiWayType) -> Void
var ways: [AppLogiWayType] = [.password, .qq, .mobile]
var body: some View {
HStack(spacing: 30.baobao.less, content: {
ForEach(ways) { way in
Button {
wayAction(way)
} label: {
VStack(spacing: 4, content: {
Image(way.image_name)
.resizable()
.renderingMode(.original)
.scaledToFit()
.frame(width: 46.baobao.less, height: 46.baobao.less, alignment: .center)
Text(way.title)
.font(.custom(AppFontName.regular.rawValue, size: 12.baobao.less))
.foregroundColor(Color("text_main", bundle: nil))
}).padding(0)
}
.background(Color.clear)
}
})
.padding(0)
.edgesIgnoringSafeArea(.all)
.navigationBarHidden(true)
.onAppear(perform: {
if let nav = UIApplication.shared.baobao.getCurrentVC()?.navigationController {
nav.isNavigationBarHidden = true
nav.navigationItem.hidesBackButton = true
nav.navigationBar.isHidden = true
}
})
}
}
UIViewController與SwiftUI的狀態(tài)記錄與交互問題
1.ObservableObject 管理狀態(tài)
2.Toggle使用
3.自定義ToggleStyle
class AgreementState: ObservableObject {
@Published var isAgreed: Bool
init(isAgreed: Bool) {
self.isAgreed = isAgreed
}
}
// ObservableObject 管理狀態(tài)
private var agreementState = AgreementState(isAgreed: App.Config.shared.is_agree_login_protocol)
private lazy var agreementView = LoginAgreementView(state: agreementState, clickAction: {[weak self] agreement in
self?.didAgreementClicked(agreement)
}, onToggle: { [weak self] isOn in
guard let self = self else { return }
self.agreementState.isAgreed = isOn
App.Config.shared.is_agree_login_protocol = isOn
baobaoLog(".isAgree = \(self.agreementState.isAgreed), app.agree = \(App.Config.shared.is_agree_login_protocol)")
})
struct LoginAgreementView: View {
@ObservedObject var state: AgreementState
// @Binding var isAgreed: Bool
var protocls: [ProtocolModel] = [ProtocolConfig.shared.user, ProtocolConfig.shared.privacy]
var clickAction: (ProtocolModel) -> Void
var onToggle: (Bool) -> Void
var body: some View {
HStack(spacing: 8.less, content: {
Toggle(isOn: $state.isAgreed, label: {
HStack(spacing: 0, content: {
Text("我已閱讀并同意")
.font(.custom(getFontName(style: .regular), size: 12.less))
.foregroundColor(Color("text"))
ForEach(protocls, id: \.url) { agreement in
AgreementTextView(text: agreement.title, action: {
clickAction(agreement)
})
}
})
})
.toggleStyle(CheckBoxToggleStyle(onToggle: onToggle))
})
.padding(0)
.fixedSize()
.edgesIgnoringSafeArea(.all)
.navigationBarHidden(true)
.onAppear(perform: {
if let nav = UIApplication.topViewController()?.navigationController {
nav.isNavigationBarHidden = true
nav.setNavigationBarHidden(true, animated: false)
}
})
}
}
//#Preview {
// LoginAgreementView()
//}
struct AgreementTextView: View {
let text: String
let action: () -> Void
var body: some View {
Text(text)
.foregroundColor(Color("agreement"))
.font(.custom(getFontName(style: .regular), size: 12.less))
.onTapGesture {
action()
}
}
}
struct CheckBoxToggleStyle: ToggleStyle {
let onToggle: (Bool) -> Void
func makeBody(configuration: Configuration) -> some View {
Button(action: {
configuration.isOn.toggle()
print("是否綁定 \(configuration.isOn)")
onToggle(configuration.isOn)
}) {
HStack {
Image(configuration.isOn ? .selectedBlack : .selectUnIcon)
.renderingMode(.original)
configuration.label
}
}
.buttonStyle(.plain)
.padding(0)
.background(Color.clear)
}
}