Я искал решение этой проблемы, но ни одно из найденных мной, похоже, не исправляет мою специфическую 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")
}
}
)
}
}
}