Ios 如何在SwiftUI中实现自定义委托
例如,我有一个SwitUI ContentView。当你第一次做这个项目的时候Ios 如何在SwiftUI中实现自定义委托,ios,delegates,swiftui,delegation,Ios,Delegates,Swiftui,Delegation,例如,我有一个SwitUI ContentView。当你第一次做这个项目的时候 import SwiftUI struct ContentView: View { var manager = TestManager() var body: some View { ZStack{ Color(.green) .edgesIgnoringSafeArea(.all) VStack { Text("T
import SwiftUI
struct ContentView: View {
var manager = TestManager()
var body: some View {
ZStack{
Color(.green)
.edgesIgnoringSafeArea(.all)
VStack {
Text("Test Text")
Button(action:{}) {
Text("Get number 2")
.font(.title)
.foregroundColor(.white)
.padding()
.overlay(RoundedRectangle(cornerRadius: 30)
.stroke(Color.white, lineWidth: 5))
}
}
}
}
}
我有一个TestManager来处理Api调用。我为有两个函数的类创建了一个委托
protocol TestManagerDelegate {
func didCorrectlyComplete(_ testName: TestManager, model: TestModel)
func didFailWithError(_ error: Error)
}
struct TestManager {
var delegate: TestManagerDelegate?
let urlString = "http://numbersapi.com/2/trivia?json"
func Get(){
if let url = URL(string: urlString){
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil{
self.delegate?.didFailWithError(error!)
return
}
if let safeData = data{
if let parsedData = self.parseJson(safeData){
self.delegate?.didCorrectlyComplete(self, model: parsedData)
}
}
}
task.resume()
}
}
func parseJson(_ jsonData: Data) -> TestModel?{
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(TestModel.self, from: jsonData)
let mes = decodedData.message
let model = TestModel(message: mes)
return model
} catch {
delegate?.didFailWithError(error)
return nil
}
}
}
这是testModel数据类。仅获取返回的Json文本
struct TestModel :Decodable{
let text: String
}
如何将TestManager连接到视图,并让视图像在故事板中那样处理委托?关于TestModel
协议(在您的上下文中)假定您使用通过JSON获得的所有属性创建模型结构。请求http://numbersapi.com/2/trivia?json
您将得到如下结果:
{
"text": "2 is the number of stars in a binary star system (a stellar system consisting of two stars orbiting around their center of mass).",
"number": 2,
"found": true,
"type": "trivia"
}
也就是说,您的模型应该如下所示:
struct TestModel:可解码{
让文本:字符串
编号:Int
让我发现:布尔
let类型:String
}
关于代表
在SwiftUI中,这种方法是无法实现的。相反,开发人员需要调整Combine框架的功能:属性包装器@ObservedObject
,@Published
,以及observeObject
协议。
你想把你的逻辑放到某个结构中。坏消息是,(目前)observateObject
是AnyObject
协议(即)。您需要将TestManager
重写为类,如下所示:
类测试管理器:ObservableObject{
// ...
}
只有这样,您才能使用属性包装器在CurrentView
中使用它:
struct ContentView:View{
@ObservedObject变量管理器=TestManager()
// ...
}
关于TestManager
您的逻辑现在排除了委托
,因此您需要使用TestModel
将数据传递给CustomView
。您可以通过使用属性包装器添加新属性来修改TestManager
:
类测试管理器:ObservableObject{
让URL字符串=”http://numbersapi.com/2/trivia?json"
// 1
@发布的var模型:TestModel?
func get(){
如果let url=url(字符串:urlString){
let session=URLSession(配置:。默认值)
让task=session.dataTask(带有:url){[weak self](数据、响应、错误)在
// 2
DispatchQueue.main.async{
如果让safeData=data{
如果让parsedData=self?.parseJson(安全数据){
// 3
self?.model=parsedData
}
}
}
}
task.resume()
}
}
私有func parseJson(jsonData:Data)->TestModel{
let decoder=JSONDecoder()
做{
让decodedData=try decoder.decode(TestModel.self,from:jsonData)
返回解码数据
}抓住{
归零
}
}
}
ContentView
DispatchQueue.main.async{}
,因为不允许从后台线程发布更改;确保在模型更新时从主线程(通过诸如receive(on:)之类的运算符)发布值。ContentView
中使用TestManager
如下:
struct ContentView:View{
@ObservedObject变量管理器=TestManager()
var body:一些观点{
ZStack{
颜色(.绿色)
.edgesIgnoringSafeArea(.all)
VStack{
文本(“琐事是:\(self.manager.model?.Text??“未知”))
按钮(操作:{self.manager.get()}){
文本(“获取编号2”)
.font(.title)
.foregroundColor(.白色)
.padding()
.叠加(圆角半径:30)
.笔划(颜色.白色,线宽:5))
}
}
}
}
}
关于HTTP
您使用链接http://numbersapi.com/2/trivia?json
也就是说,请改用https
,或者添加应用程序传输安全设置
键,并将允许任意加载
参数设置为是
。但这样做是因为http链接根本不起作用
进一步步骤
根据上面的描述,您可以自己实现错误处理
完整代码(复制粘贴并执行):
导入快捷界面
结构ContentView:View{
@ObservedObject变量管理器=TestManager()
var body:一些观点{
ZStack{
颜色(.绿色)
.edgesIgnoringSafeArea(.all)
VStack{
文本(“琐事是:\(self.manager.model?.Text??“未知”))
按钮(操作:{self.manager.get()}){
文本(“获取编号2”)
.font(.title)
.foregroundColor(.白色)
.padding()
.叠加(圆角半径:30)
.笔划(颜色.白色,线宽:5))
}
}
}
}
}
结构内容视图\u预览:PreviewProvider{
静态var预览:一些视图{
ContentView()
}
}
类TestManager:ObservableObject{
让URL字符串=”http://numbersapi.com/2/trivia?json"
@发布的var模型:TestModel?
func get(){
如果let url=url(字符串:urlString){
let session=URLSession(配置:。默认值)
让task=session.dataTask(带有:url){[weak self](数据、响应、错误)在
DispatchQueue.main.async{
如果让safeData=data{
如果让parsedData=self?.parseJson(安全数据){
self?.model=parsedData