我有一个视图,其中用户能够输入一些文本到一个TextField。我希望能够获得在TextField中输入的文本,并在结构中使用此值。这个应用程序的概念是,它显示太阳的仰角程度。为了能够做到这一点,它需要从WebPage中抓取值。然而,要使这个应用程序动态化,用户必须能够编辑url (您可以更改url中的位置、日期等)。我认为这将是相当容易的,因为我只需要获取一些文本,并在加载url之前编辑url。我已经能够将值传递到视图中,但是我需要在结构中使用它。也许我的代码布局是错误的,也许我应该获取数据并在视图中绘制函数?我不知道。这是我第一次用swift编码。
我想更改纬度变量。
这是我的代码:
视图1(输入):
class ViewModel: ObservableObject {
    @Published var latitude:String = ""
    @Published var page = 0
}
struct ContentView: View {
    @EnvironmentObject var value1: ViewModel
    
    var body: some View {
        if value1.page == 0{
            VStack{
            TextField("", text: $value1.latitude)
            Button(action:{ value1.page = 1}){
                Text("To next view")
            }.frame(width: 300, height: 100, alignment: .center)
        }
    } else {
        elevationGraph()
    }
}
}视图2(图表)
struct getHtml { 
    var url = URL(string: "https://midcdmz.nrel.gov/apps/spa.pl?syear=2020&smonth=1&sday=1&eyear=2020&emonth=1&eday=1&otype=0&step=60&stepunit=1&hr=12&min=0&sec=0&latitude=\(latitude)&longitude=10.757933&timezone=1.0&elev=53&press=835&temp=10&dut1=0.0&deltat=64.797&azmrot=180&slope=0&refract=0.5667&field=0")
    
    func loadData(from url: URL?) -> String {
        guard let url = url else {
            return "nil"
        }
        let html = try! String(contentsOf: url, encoding: String.Encoding.utf8)
        
        return html
        
    }
}
struct elevationFunction: Shape {
var url: URL? //This only works in views, is there a way to do it in shape structs?
    
    let html = getHtml.init().loadData(from: getHtml.init().url)
    private func dbl1() -> Double {
        
        let leftSideOfTheValue = "0:00:00,"
        
        let rightSideOfTheValue = "\(month)/\(day)/\(year),1:00:00,"
        
        guard let leftRange = html.range(of: leftSideOfTheValue) else {
            print("cant find left range")
            return 0
        }
        
        guard let rightRange = html.range(of: rightSideOfTheValue) else {
            print("cant find right range")
            return 0
        }
        
        let rangeOfTheValue = leftRange.upperBound..<rightRange.lowerBound
        
        return Double(html[rangeOfTheValue].dropLast()) ?? 90
    }
    
    
    func path(in rect: CGRect) -> Path {
        var path = Path()
        
        path.move(to: CGPoint(x: 10, y: (125 - (90-dbl1()))))
        path.addLine(to: CGPoint(x: 120, y: (125 - (90-45))))
        path.addLine(to: CGPoint(x: 250, y: (125 - (90-dbl1()))))
    
        var scale = (rect.height / 350) * (9/10)
        var xOffset = (rect.width / 6)
        var yOffset = (rect.height / 2)
        
        return path.applying(CGAffineTransform(scaleX: scale, y: scale)).applying(CGAffineTransform(translationX: xOffset, y: yOffset))
        
        
    }
}
struct elevationGraph: View {
        var body: some View {
            GeometryReader { geometry in 
                ZStack {
                    elevationFunction().stroke(LinearGradient(gradient: Gradient(colors: [Color.yellow, Color.red]), startPoint: .top , endPoint: .bottom), style: StrokeStyle(lineWidth: 6.0)).aspectRatio(contentMode: .fill)
    
                }
            .frame(width: 600, height: 800, alignment: .center)
        }
    }
}发布于 2021-01-26 01:04:24
正如我在评论中提到的,您可以像传递常规View一样将参数传递给Shape
elevationFunction(url: yourURL)最佳实践是将其大写,并将其命名为...Shape:elevationFunction变为ElevationShape
关于注释中的第二个问题,首先,您可能希望修复getHtml的命名,原因与上面相同--不大写,它看起来像一个变量名。也许是像DataLoader这样的。
关于崩溃,您有一些循环逻辑在运行--调用getHtml.init(),然后再次传递从getHtml.init()派生的参数。为什么不直接调用getHtml()并让它从自己的内部URL属性执行loadData呢?
不过,还有一个更大的问题,那就是您在Shape上将html声明为let属性,每次呈现Shape时都会重新创建该属性。因此,在每次渲染时,使用您当前的代码,您将创建2个新的getHtmls并尝试加载数据(这实际上可能没有时间加载URL请求)。这很可能会阻塞Shape的第一次渲染,并且几乎肯定会导致循环和重复逻辑中的某个地方崩溃。
相反,您可能希望考虑将URL请求移动到onAppear或作为ObservableObject的一部分,在这种情况下,您可以更多地控制这些数据的加载时间和频率。这里有一个很好的资源,可以了解有关使用URLSession和SwiftUI加载数据的更多信息:https://www.hackingwithswift.com/books/ios-swiftui/sending-and-receiving-codable-data-with-urlsession-and-swiftui
https://stackoverflow.com/questions/65880559
复制相似问题