渲染UI的时候必须回到主线程
通过**print(Thread.isMainThread) 来得知是否现在主线程(这是基于foundation的)**
Thread.iscurrent也可以知道是在哪个线程。主线程的线程序号是1,名字是main,子线程是随机生成的,没有名字。
用这个方法来新建线程,具体是哪条是系统随机分配的
swift
DispatchQueue.global().async {
//一些代码
}
一个函数的执行顺序是先把自己的内容执行完,然后按随机顺序执行其他线程的内容。
需要用到这个model里的内容去刷新UI界面(比如设置UI界面的文本或者图片),所以在参数里用一个逃逸闭包,把model传出去。
注意这里的model最后是要用来渲染UI的,所以必须在用回调传出model的时候回到主线程
swift
func getDetailRequest(block: @escaping ResponseBlock) {
let dic = ["sys_lan": "1", "result_str": "INFJ"]
//把dic转成JSON再在URLRequest函数里使用
let jsonStr = dicValuesString(dic as [String : Any])
print(jsonStr)//这里也有啊
postRequest(jsonStr: jsonStr, url: RequestSimpleReport.simpleBaseUrl) {
[weak self] dic in
// print (dic)
if let arr = dic as? [Dictionary<String, Any>] {
if arr.count == 0 {
self?.responseBlock?(nil)
return
} else {
let model = SimpleReportModel.base(with: arr[0])
DispatchQueue.main.async {
block(model)
}
// print(model)
}
}
}
}
用SwiftUI写一个组件,然后在ViewController里设置它的大小和位置。
需要用什么就把什么传进来。需要用到model,把model传进来。
swift
import SwiftUI
struct ReportView: View {
var model: SimpleReportModel
var body: some View {
Image(systemName: "camera").frame(width: 50, height: 50)
Text(model.result_str).font(.system(size: 16)).foregroundColor(.blue)
}
}
然后要用UIKit做底层,也就是在UIViewController里把SwiftUI写好的View导入进去,然后设置
swift
lazy var reportView: UIHostingController<ReportView> = {
let reportView = UIHostingController(rootView: ReportView(model: SimpleReportModel.empty()))
reportView.view.frame = .init(origin: .zero, size: self.view.frame.size)
return reportView
}()
lazy var reportView: UIHostingController<ReportView>用于桥接SwiftUI和UIKit
初始化reportView,UIHostingController是通过获取根视图来初始化的,现在model里还没东西就随便传一个进去(这个model是没有值的所以必须传值)。
然后在需要显示的ViewController调用网络请求函数时,把从网络上请求到的model传给reportView的rootView,就可以使用model渲染页面了。
就像这样:
