Refre sh Данные в SwiftUI View, полученные из HTTP-запроса - PullRequest
0 голосов
/ 09 июля 2020

Я искал решение этой проблемы, но ни одно из найденных мной, похоже, не исправляет мою специфическую c ситуацию. Надеюсь, с этими подробностями кто-нибудь сможет мне помочь. Я новичок в Swift, так что терпите меня. Я работаю с REST Api и HTTP-запросом из нашей системы тикетов службы поддержки. Я пытаюсь найти способ обновить sh данные автоматически, когда что-то изменится, а также есть способ вручную обновить sh, то есть кнопку вытягивания или фактического обновления sh. Если я смогу понять это для двух сценариев ios ниже, я думаю, что смогу применить его к остальной части моего сценария ios.

Сценарий № 1 - я отправляю новую заметку для заявки, но подробный вид не изменится, чтобы отразить эту новую заметку. Мне нужно go вернуться и снова открыть представление, чтобы увидеть изменения.

введите описание изображения здесь

Получить детали билета

struct TicketDetails: Codable, Identifiable {
    var id: Int
    var type: String
    var location: Location
    var detail: String
    var notes: [Notes]
    var statustype: StatusType
}

struct Location: Codable {
    let locationName: String
}

struct Notes: Codable {
    var prettyUpdatedString: String?
    var mobileNoteText: String?
}

struct StatusType: Codable {
    var id: Int
    var statusTypeName: String
}

class FetchTick: ObservableObject {
    func getTicket(id: Int, userApi: String, completion: @escaping (TicketDetails) -> ()) {
        guard let url = URL(string: "URL FOR TICKET DATA") else { return }
        URLSession.shared.dataTask(with: url) {(data, _, _) in
            let ticket = try! JSONDecoder().decode(TicketDetails.self, from: data!)
            DispatchQueue.main.async {
                completion(ticket)
            }
        }
        .resume()
    }
}

Создать новую заметку в билете

class CreateTicketNote: ObservableObject {
    func CreateNoteAction(ticketId: Int, userApi: String, techNote: String) {
        
        let ticketUrl = URL(string:
            "URLFORTICKET")!

        var request = URLRequest(url: ticketUrl)
        request.httpMethod = "POST"
        
        
        let json: [String: Any] = [
            "noteText": techNote,
            "jobticket": [
                "id": ticketId,
                "type": "Ticket"
                ]
        ]
        
        let data = try! JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)

        
        URLSession.shared.uploadTask(with: request, from: data) { (responseData, response, error) in
            if let error = error {
                print("Error making POST request: \(error.localizedDescription)")
                return
            }
            
            if let responseCode = (response as? HTTPURLResponse)?.statusCode, let responseData = responseData {
                guard responseCode == 200 else {
                    print("Invalid response code: \(responseCode)")
                    return
                }
                
                if let responseJSONData = try? JSONSerialization.jsonObject(with: responseData, options: .allowFragments) {
                    print("Response JSON data = \(responseJSONData)")
                }
            }
        }.resume()
    }
}

Подробный вид

struct DetailsView: View {
    @ObservedObject var ticketStatusAction = TicketStatusAction()
    @ObservedObject var createTicketNote = CreateTicketNote()
    @State var ticket: [TicketDetails] = []
    @State private var showingNoteAlert = false
    @State private var showingOpenAlert = false
    @State private var showingPendingAlert = false
    @State private var showingDepotAlert = false
    @State private var showingCloseAlert = false
    @State private var note: String = ""

    var id: Int
    var displayClient: String
    @Binding var userApi: String
    
    var body: some View {
        ScrollView(.vertical){
            VStack(alignment: .leading){
                if !ticket.isEmpty {
                           Text(self.ticket.first?.location.locationName ?? "")
                                .fontWeight(.bold)
                                .padding()

                           }
                
                
                Text("\(displayClient) - \(id)")
                    .fontWeight(.bold)
                    .font(.system(size:20))
                    .padding()

                Divider()
                
                Text("Status")
                    .fontWeight(.bold)
                    .padding()
                
                if !ticket.isEmpty {
                    Text(self.ticket.first?.statustype.statusTypeName ?? "")
                    .padding()
                }
                
                Text("Details")
                .fontWeight(.bold)
                .padding()
                
                if !ticket.isEmpty {
                    Text(clearMarkdown(on:self.ticket.first?.detail ?? ""))
                               .padding()
                    .fixedSize(horizontal: false, vertical: true)

                           }
                Divider()

                Text("Most Recent Note")
                .fontWeight(.bold)
                .padding()
                
                if !ticket.isEmpty {
                    Text(clearMarkdown(on: self.ticket.first?.notes.first?.prettyUpdatedString ?? ""))
                           .padding()
                    Text(clearMarkdown(on: self.ticket.first?.notes.first?.mobileNoteText ?? ""))
                           .padding()
                    .fixedSize(horizontal: false, vertical: true)
                       }
            }
            .onAppear {
                FetchTick().getTicket(id: self.id, userApi: self.userApi) { (ticketDetails) in
                    self.ticket = [ticketDetails]
                }}
            
            Divider()

               Section(header: Text("Create New Note")
                   .fontWeight(.bold)
                   .padding()
                   .padding(10)
                   .frame(maxWidth: .infinity)) {
                       
                   TextField("Enter your note", text: $note)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .frame(width: 350)
                    .padding(15)

                   
                   Button(action: {
                       self.showingNoteAlert = true
                   }) {
                       Text("Submit Note")
                       .frame(width: 300)
                       .padding(15)
                       .foregroundColor(Color.white)
                       .background(Color.orange)
                       .cornerRadius(5)
                   }.buttonStyle(BorderlessButtonStyle()
                   ).actionSheet(isPresented:self.$showingNoteAlert) {
                       ActionSheet(
                           title: Text("Are you sure you want to add this note to \(displayClient)'s ticket?"),
                           message: Text("\(self.note)"),
                           buttons: [
                        .default(Text("Submit"))
                            {
                                self.createTicketNote.CreateNoteAction(ticketId: self.id, userApi: self.userApi, techNote: self.note);
                                self.note = ""
                            },
                        .cancel(){
                            self.note = ""
                            }])
                   }
               }
            
            Divider()

            Section(header: Text("Change Ticket Status")
                .fontWeight(.bold)
                .padding()
                .padding(10)
                .frame(maxWidth: .infinity)) {
                                    
                Button(action: {
                    self.showingOpenAlert = true
                }) {
                    Text("Open")
                    .frame(width: 300)
                    .padding(15)
                    .foregroundColor(Color.white)
                    .background(Color.green)
                    .cornerRadius(5)
                }.buttonStyle(BorderlessButtonStyle()).alert(isPresented:self.$showingOpenAlert) {
                    Alert(
                        title: Text("Are you sure you want change \(displayClient)'s ticket to Open?"),
                        primaryButton: .default(Text("Open"))
                            {
                                self.ticketStatusAction.TicketAction(ticketId: self.id, userApi: self.userApi, desiredStatus: 1)
                            },
                        secondaryButton: .cancel())
                }
                Spacer()
                Button(action: {
                    self.showingPendingAlert = true
                }) {
                    Text("Pending")
                    .frame(width: 300)
                    .padding(15)
                    .foregroundColor(Color.white)
                    .background(Color.yellow)
                    .cornerRadius(5)
                }.buttonStyle(BorderlessButtonStyle()).alert(isPresented:self.$showingPendingAlert) {
                    Alert(
                        title: Text("Are you sure you want to set \(displayClient)'s ticket to Pending?"),
                        primaryButton: .default(Text("Pending"))
                            {
                                self.ticketStatusAction.TicketAction(ticketId: self.id, userApi: self.userApi, desiredStatus: 2)
                            },
                        secondaryButton: .cancel())
                }
                Spacer()
                Button(action: {
                    self.showingDepotAlert = true
                }) {
                    Text("Depot")
                    .frame(width: 300)
                    .padding(15)
                    .foregroundColor(Color.white)
                    .background(Color.blue)
                    .cornerRadius(5)
                    
                }.buttonStyle(BorderlessButtonStyle()).alert(isPresented:self.$showingDepotAlert) {
                    Alert(
                        title: Text("Are you sure you want to depot \(displayClient)'s ticket?"),
                        primaryButton: .default(Text("Depot"))
                            {
                                self.ticketStatusAction.TicketAction(ticketId: self.id, userApi: self.userApi,
 desiredStatus: 6)
                            },
                        secondaryButton: .cancel())
                }
                Spacer()
                Button(action: {
                    self.showingCloseAlert = true
                }) {
                    Text("Close")
                    .frame(width: 300)
                    .padding(15)
                    .foregroundColor(Color.white)
                    .background(Color.red)
                    .cornerRadius(5)
                }.buttonStyle(BorderlessButtonStyle()).alert(isPresented:self.$showingCloseAlert) {
                    Alert(
                        title: Text("Are you sure you want to close \(displayClient)'s ticket?"),
                        primaryButton: .destructive(Text("Close"))
                            {
                                self.ticketStatusAction.TicketAction(ticketId: self.id, userApi: self.userApi, desiredStatus: 3)
                            },
                        secondaryButton: .cancel())
                }
                Spacer()
            }
        }
    }
}

Сценарий № 2 - я просматриваю список билетов и хочу убедиться, что не открылись дополнительные билеты. Я хочу обновить sh список и показать новые билеты.

Фет-билеты по местоположению

struct TicksByLocation: Codable, Identifiable {
    public var id: Int
    public var type: String
    public var displayClient: String
    public var shortDetail: String
}

class FetchTicksByLocation: ObservableObject {
    
    func getTicksByLocation(ticketLocation: String, userApi: String, completion: @escaping (([TicksByLocation]) -> ())){
    
    guard let url = URL(string: "URLFORTICKETS") else {
        return
    }
        URLSession.shared.dataTask(with: url) {(data, response, error) in
            do {
                if let tickData = data {
                    let decodedData = try JSONDecoder().decode([TicksByLocation].self, from: tickData)
                    DispatchQueue.main.async {
                        completion(decodedData)
                    }
                } else {
                    print("No data")
                }
            } catch {
                print("Error")
            }
        }.resume()
    }
}

Показать билеты по местоположению

struct ShowLocationView: View {
    @Binding var ticketLocation: String
    @Binding var userApi: String
    @Binding var tickets: [TicksByLocation]
    @State var openTickets: [TicksByStatusAndLocation] = []
    @State var green = Color.green
    @State var yellow = Color.yellow
    @State var blue = Color.blue
    @State var purple = Color.purple



    var body: some View {
        NavigationView{
            List(tickets) { tick in
                VStack(alignment: .leading, spacing: 10) {
                    Text("\(tick.id)")
                        .font(.system(size: 11))
                        .cornerRadius(5)
                    
                    Text(tick.displayClient)

                    Text(tick.shortDetail)
                        .font(.system(size: 11))
                        .foregroundColor(Color.gray)
                    NavigationLink(destination: DetailsView(
                        id: tick.id,
                        displayClient: tick.displayClient,
                        userApi: self.$userApi
                    )) {
                       Text("See Details")
                        .foregroundColor(Color.blue)

                        }
                    Divider()
                    }
            }
            .navigationBarTitle(
                Text("\(ticketLocation) - All (\(tickets.count))"),
                displayMode: .inline
            )
            .navigationBarItems(
                trailing:
                Text("Filter")
                .contextMenu {
                 NavigationLink(
                    destination: ShowLocationAndStatusView(
                        ticketLocation: $ticketLocation,
                        userApi: $userApi,
                        status: "Open",
                        color: green
                        )
                    ) {
                 Text("Open")
                   }
                    
                NavigationLink(
                   destination: ShowLocationAndStatusView(
                       ticketLocation: $ticketLocation,
                       userApi: $userApi,
                       status: "Pending",
                       color: yellow
                       )
                   ) {
                Text("Pending")
                  }
                    
                NavigationLink(
                   destination: ShowLocationAndStatusView(
                       ticketLocation: $ticketLocation,
                       userApi: $userApi,
                       status: "Depot",
                       color: blue
                       )
                   ) {
                Text("Depot")
                  }
                    
                NavigationLink(
                   destination: ShowLocationAndStatusView(
                       ticketLocation: $ticketLocation,
                       userApi: $userApi,
                       status: "Agi",
                       color: purple
                       )
                   ) {
                Text("Agi")
                  }
                    
                }
            )
        }
    }
}

1 Ответ

0 голосов
/ 15 июля 2020

Решение №1

Section(header: Text("Create New Note")
                   .fontWeight(.bold)
                   .padding()
                   .padding(10)
                   .frame(maxWidth: .infinity)) {
                       
                   TextField("Enter your note", text: $note)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .frame(width: 350)
                    .padding(15)

                   
                   Button(action: {
                       self.showingNoteAlert = true
                   }) {
                       Text("Submit Note")
                       .frame(width: 300)
                       .padding(15)
                       .foregroundColor(Color.white)
                       .background(Color.orange)
                       .cornerRadius(5)
                   }.buttonStyle(BorderlessButtonStyle()
                   ).actionSheet(isPresented:self.$showingNoteAlert) {
                       ActionSheet(
                           title: Text("Are you sure you want to add this note to \(displayClient)'s ticket?"),
                           message: Text("\(self.note)"),
                           buttons: [
                        .default(Text("Submit"))
                            {
                                self.createTicketNote.CreateNoteAction(ticketId: self.id, userApi: self.userApi, techNote: self.note);
                                self.note = "";
                                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                                    FetchTick().getTicket(id: self.id, userApi: self.userApi) { (ticketDetails) in
                                        self.ticket = [ticketDetails]
                                    }
                                }
                            },
                        .cancel(){
                            self.note = ""
                            }])
                   }
               }

Решение №2

Использование https://github.com/phuhuynh2411/SwiftUI-PullToRefresh

import SwiftUI
import UIKit

struct ShowSelectedStatus: View {
    @State private var isShowing = false
    @Binding var userApi: String
    @Binding var tickets: [TicksByStatus]
    var ticketStatus: String
    var color: Color

    var body: some View {
        NavigationView{
            List(tickets) { tick in
                VStack(alignment: .leading, spacing: 10) {
                    
                    Text(tick.displayClient)
                    .padding(10)
                    .background(self.color)
                    .cornerRadius(5)

                    Text(tick.shortDetail)
                        .font(.system(size: 11))
                        .foregroundColor(Color.gray)
                    NavigationLink(destination: DetailsView(
                        id: tick.id,
                        displayClient: tick.displayClient,
                        userApi: self.$userApi
                    )) {
                       Text("See Details")
                        .foregroundColor(Color.blue)

                        }
                    Divider()
                    }
            }
            .pullToRefresh(isShowing: $isShowing) {
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    self.isShowing = false
                }
                FetchTicksByStatus().getTicksByStatus(
                    ticketStatus: self.ticketStatus,
                    userApi: self.userApi
                 ) {
                    (ticks) in self.tickets = ticks
                    }
            }
            .navigationBarTitle(
                Text("\(ticketStatus) (\(tickets.count))"),
                displayMode: .inline
            )
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...