我正在SwiftUI中开发一个应用程序来管理虚拟数据中心(服务器,防火墙规则,负载平衡器...)。我附上的代码摘自该应用程序的摘录,以显示我目前所面临的问题,无法自己解决。 问题(或SwiftUI错误?)如下:
使用附带的代码复制此问题的方法如下:
我正在MacOS 10.15.2上使用Xcode 11.3运行它。欢迎任何帮助或提示!
import SwiftUI
struct ContentView: View {
@State var selectedTab = 1
var body: some View {
TabView(selection: $selectedTab){
CreateView(selectedTab: $selectedTab)
.tabItem {
Image(systemName: "plus")
Text("Create")
}.tag(0)
ListView()
.tabItem {
Image(systemName: "cloud")
Text("List")
}.tag(1)
}
}
}
struct CreateView: View {
@Binding var selectedTab: Int
var body: some View {
VStack{
NavigationView{
List{
Text("Server")
NavigationLink(destination: CreateFirewallPolicyView(selectedTab: $selectedTab)){
Text("Firewall Policy")
}
}
.navigationBarTitle("Select the element you want to create", displayMode: .inline)
}
}
}
}
struct ListView: View {
var body: some View {
NavigationView{
List{
Section(header: Text("Servers")){
Text("Server 1")
Text("Server 2")
}
Section(header: Text("Firewall policies")){
Text("Firewall 1")
Text("Firewall 2")
}
}
.navigationBarTitle("My virtual datacenter", displayMode: .large)
}
}
}
struct CreateFirewallPolicyView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@Binding var selectedTab: Int
@State private var name: String = ""
@State private var allowed_ip: String = ""
@State private var ports: String = ""
@State private var description: String = ""
@State private var selectedAction = RuleAction.allow
@State private var selectedProtocol = NetworkProtocol.tcp
@State private var rules: [Rule] = []
var body: some View {
Form {
Section(header: Text("Name of the firewall policy")){
TextField("Nombre", text: $name)
}
Section(header: Text("New rule")){
Picker(selection: $selectedAction, label: Text("Action")) {
ForEach(RuleAction.allCases, id:\.self) { fw_action in
Text(fw_action.name)
}
}
if (selectedAction == RuleAction.allow){
TextField("Allowed IP", text: $allowed_ip)
Picker(selection: $selectedProtocol, label: Text("Protocol")) {
ForEach(NetworkProtocol.allCases, id:\.self) { fw_protocol in
Text(fw_protocol.name)
}
}
TextField("Ports", text: $ports)
}
TextField("Description", text: $description)
Button(action: {
if self.selectedAction == RuleAction.deny{
self.ports = ""
self.allowed_ip = ""
self.selectedProtocol = NetworkProtocol.any
}
self.rules.append(Rule(id: UUID().uuidString, protocol: self.selectedProtocol, port: (self.ports.isEmpty ? nil : self.ports), source: (self.allowed_ip.isEmpty ? "0.0.0.0" : self.allowed_ip), description: (self.description.isEmpty ? nil : self.description), action: self.selectedAction))
self.allowed_ip = ""
self.ports = ""
self.description = ""
self.selectedAction = RuleAction.allow
self.selectedProtocol = NetworkProtocol.tcp
}) {
HStack{
Spacer()
Text("Add new rule")
}.disabled(self.selectedAction == RuleAction.allow && (self.selectedProtocol == NetworkProtocol.tcp || self.selectedProtocol == NetworkProtocol.udp || self.selectedProtocol == NetworkProtocol.tcp_udp) && self.ports.isEmpty)
}
}
Section(header: Text("Rules to add")){
ForEach(self.rules, id:\.self) { rule in
Text("\(rule.action.rawValue.capitalized) - \(rule.source ?? "all") - \(rule.protocol.rawValue) - \(rule.port ?? "")")
}.onDelete(perform: delete)
}
}
.navigationBarTitle("Create Firewall Policy")
.navigationBarBackButtonHidden(true)
.navigationBarItems(
leading:
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Cancel")
},
trailing:
Button(action: {
print("Create")
}) {
Text("Create")
}
.disabled(name.isEmpty || rules.count == 0)
)
}
func delete(at offsets: IndexSet) {
rules.remove(atOffsets: offsets)
}
}
struct Rule:Codable, Hashable, Identifiable{
let id: String
var `protocol`: NetworkProtocol
var port: String?
var portFrom: Int?
var portTo: Int?
var source: String?
var description: String?
var action: RuleAction
}
enum NetworkProtocol: String, Codable, Hashable, CaseIterable{
case tcp = "TCP"
case udp = "UDP"
case icmp = "ICMP"
case tcp_udp = "TCP/UDP"
case ipsec = "IPSEC"
case gre = "GRE"
case any = "ANY"
var name: String {
return "\(self.rawValue)"
}
}
enum RuleAction: String, Codable, Hashable, CaseIterable{
case allow
case deny
var name: String {
return "\(self)".capitalized
}
}