Детальный просмотр из другой модели данных (ответ API) в swiftUI

Углубленная проработка проблемы с помощью кода

У меня есть модель данных (ответ API), с помощью которой я создаю список. Элементы списка также должны отображать свои детали в подробном представлении. Проблема заключается в том, что сведения об элементах списка поступают из другого API, отличного от API, используемого для создания списка. Идентификатор одного элемента передается в API, который в ответ предоставляет сведения об элементе.

Это модель данных (включая элементы только для конкретной проблемы):

struct TrackSample : Codable, Identifiable {
    let id = UUID()
    let success : Bool
    let message : String
    let trackResponse : [TrackResponse]

    enum CodingKeys: String, CodingKey{
    case success = "IsSuccess"
    case message = "Message"
    case trackResponse = "ResponseData"
    }}

struct TrackResponse : Codable, Identifiable {
    let id = UUID()
    let patientID : String
    let name : String
    let testCount : Int
//..some more//

enum CodingKeys: String, CodingKey {
    case patientID = "PatientId"
    case name = "Name"
    case status = "Status"
case testCount = "NoOfTests"
    }}

ViewModel для получения ответа API ( TrackResource() — это другой класс, реализующий сетевой вызов):

class TrackViewModel : ObservableObject
    {
        @Published var trackReport = [TrackResponse]()
        @Published var navigate:Bool = false
        //other var
        private let trackResource = TrackResource()

    func getTrack()
    {
    //code to get data based on which button is clicked in Options 
    screen. 
    There are five options to choose:
    if else statement follows//
        
    centerID = "100"
    
        let trackRequest = TrackRequest(CenterId:centerID, 
    SearchText:searchText, StartDate:startDate, EndDate:endDate)
     trackResource.track(trackRequest: trackRequest)
        {
         response in
         if(response?.success==true)
          {
                DispatchQueue.main.async {
                self.navigate = true
                self.trackReport = response?.trackResponse ?? []
            }
        }
        else
        {
            DispatchQueue.main.async {
                self.errorMessage = response?.message ?? "No Data"
             //   self.isPresentingAlert
            }
        }}}}

Представление YdaySample, представляющее список:

struct YdaySample: View {

@ObservedObject var tracking : TrackViewModel

    var body: some View {

    NavigationView{

        List{
         ForEach(tracking.trackReport)
            { truck in
             NavigationLink(destination: TrackDetail(track:truck))
                        {
                            YdayRow(truck: truck)
                        }
                }
         if(tracking.trackReport.isEmpty){
        Text("No Record Found !")
            //formatting
        }}}}}

struct YdaySample_Previews: PreviewProvider {
static var previews: some View {
 YdaySample(tracking: TrackViewModel())
         }}

YdayRow() :

      struct YdayRow: View {
     var truck : TrackResponse
     var body: some View {
     VStack{
         HStack{
                Text(truck.name)
            //formatting//
        }
    HStack{
            Text("P.Id:")
            //formatting//
            Text(truck.patientID)
            //formatting//
    
        Spacer()
        Text("Total Test:")
            //formatting//
        Text("\(truck.testCount)")
            //formatting//
    }}}}

  struct YdayRow_Previews: PreviewProvider {
         static var previews: some View {
        YdayRow(truck: TrackResponse(patientID: "1", name: "test", 
  status: "null", crmNo: "null", 
      recordDate: "somedate", uniqueID: "null", testCount: 4))
        }
    }

TrackDetail() обновлен:

 struct TrackDetail: View {

 var track: TrackResponse
 @State var patientDetail: DetailResponse
 
 var body: some View {
        VStack{
            HStack{
                Text(track.name)
                   //formatting
                    }.frame(maxWidth: .infinity, alignment: .center)
            
                HStack{
                Text("P.Id:")
                        //formatting
                    Text(track.patientId)
                       //formatting
               
               }
           
                List{ForEach(patientDetail.detailResponse)
                        {detail in
                            HStack
                        { Text("Barcode: ")
                            Text(detail.barcode)
                        }
                    }
                }.onAppear{
                    Task{
                        do{
                            try await getDetail()
                        }catch{
                Alert(title: Text("Error"),message: Text("Not Found"), 
            dismissButton: .cancel())
                        }}}}}

func getDetail() async throws{
    
  
    var urlComponents = URLComponents()
    urlComponents.scheme = "http"
    urlComponents.host = "xx.xxx.xx.xx"
    urlComponents.path = "/api/reports/getalltests"
    urlComponents.queryItems = [URLQueryItem(name: "centerId", value: 
    ("\(668)")),URLQueryItem(name: "patientId", value: "\ 
    (track.patientId)")]

    let url = urlComponents.url

    var request = URLRequest(url: url!)
    print(request)
    request.setValue("application/json", forHTTPHeaderField: "Accept")
    request.setValue("application/json", forHTTPHeaderField: "Content- 
    Type")
    request.setValue("Basic xcvgjhalddjdj",forHTTPHeaderField: 
    "Authorization")
    // Send HTTP Request
    let task = URLSession.shared.dataTask(with: request) { (data, 
     response, error) in
        
        // Check if Error took place
        if let error = error {
            print("Error took place \(error)")
            return
        }
        
        // Read HTTP Response Status code
        if let response = response as? HTTPURLResponse {
            print("Response HTTP Status code: \(response.statusCode)")
        }
        
       if let data = data
        
        {
           
              let dataString = String(data:data,encoding: .utf8)
              print(dataString!)
            
             do{
                let json = try JSONDecoder().decode(DetailResponse.self, 
               from: data)
               print(json)
                DispatchQueue.main.async {
                    self.patientDetail = json
                }
             
    
            }catch{
                print("error \(error)")
            }
                      
        }
    };task.resume()
        }}



    struct TrackDetail_Previews: PreviewProvider {
    static var previews: some View {
    TrackDetail(track: TrackResponse(patientId: "4193716", name: "Dummy 
    Report HCV RNA", status: "null", crmNo: "null", recordDate: "2022- 
     04-15", uniqueId: "null", testCount: 10), patientDetail: 
     DetailResponse(success: false, message: "mess", detailResponse: 
       []))
    }}

print (запрос) печатает правильный URL-адрес по желанию, а идентификатор пациента правильный в URL-адресе (http://xxx..x.x/api/reports/getalltests/centerId=668&patientId=(tapped id))

Но выдает ошибку декодирования говорит, что "Авторизация для этого запроса отклонена" ошибка keynotfound(codingkeys(stringvalue: "ResponseData", intvalue:nil), Swift.decodingerror.context(codingpath: [],debugdescription: "Нет значения, связанного с ключом CodingKeys(stringvalue: «ResponseData», intvalue: nil) («ResponseData», базовая ошибка: nil)

struct DetailResponse : Codable{
    let success : Bool ?
    let message : String
    let detailResponse : [PatResponse]

    enum CodingKeys: String, CodingKey{
    case success = "IsSuccess"
    case message = "Message"
    case patResponse = "ResponseData"
    }}

struct PatResponse : Codable, Identifiable {    
    var barcode: String
    var:id String {barcode} 
    let testname : String?
    let packageName : String?
    let status: String?
    let sampleRecievedTime: String?
    let recordDate: String

enum CodingKeys: String, CodingKey {
    case packageName = "PackageName"
    case testname = "TestName"
    case status = "Status"
    case sampleRecievedTime = "SampleRecievedTime"
    case recordDate = "RecordDate"
    case barcode = "Barcode"
    }}

///////**************///////////////////// В подробном представлении отображаются имя и идентификатор, поскольку они поступают из TrackResponse. но статус и штрих-код не так, как они из разных API.

Когда пользователь щелкает/нажимает элемент в списке, идентификатор пациента и идентификатор центра отправляются в качестве параметров запроса в запросе GET, который в ответ предоставляет сведения, связанные с данным идентификатором пациента (идентификатор центра является постоянным). Как это реализовать?

Для этого вам не нужна модель представления, вы можете реализовать свою getDetail функцию непосредственно в своем TrackDetail представлении. Ваш идентификатор пациента должен быть track.PatientId и сделать detailPatient var a @State и необязательным, как в моем ответе. Пожалуйста, прокомментируйте, что вы не понимаете или испытываете трудности с реализацией.

burnsi 23.04.2022 19:50

@burnsi Я пытался вечером, но не смог реализовать, поскольку я пытался использовать модель представления для реализации вашего решения, которое превратилось в полный беспорядок ... теперь я попробую еще раз, без представления модели, определяющего функцию непосредственно в структуре, как вы описали, и вернуться назад, как только возможно

tintin 23.04.2022 20:00

@burnsi не работает ... можете ли вы предоставить пример кода .... после создания func нужно изменить код везде, так как он говорит, что аргумент отсутствует или, может быть, я неправильно его реализую

tintin 24.04.2022 15:42
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
3
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как насчет чего-то подобного?

struct TrackDetail: View{
    
    var track: TrackResponse
    @State var details: TrackDetails?
    
    var body: some View{
        HStack{
            //Detail implementation
        }.onAppear{
            Task{
                do{
                    try await doStuff()
                }catch{
                    //Alert
                }
            }
        }
    }
    
    func doStuff() async throws{
        // pull Details from Api
        
    }
}

он не работает пустым, как раньше .... можете ли вы предоставить пример кода

tintin 24.04.2022 12:33

@tintin, пожалуйста, обновите свой вопрос, чтобы я мог видеть, что вы уже сделали. Ответ, который я предоставил, настолько подробен, насколько я могу получить, не зная больше о коде.

burnsi 25.04.2022 11:08

я обновил вопрос, пожалуйста, посмотрите @burnsi

tintin 25.04.2022 12:07

@tintin Authrization has been denied for this request кажется, что ваш запрос сам по себе не выполняется. Вам, вероятно, нужна какая-то последовательность входа в систему, чтобы получить эти данные. Но я считаю, что это выходит за рамки этого вопроса. Пожалуйста, исследуйте дальше (возможно, погуглив или задав другой вопрос) и вернитесь, как только решите проблему.

burnsi 25.04.2022 12:41

Привет @burnsi, разрешено, все значения успешно получены .... была одна проблема ---- url.port Я не упомянул об этом явно, я упомянул об этом, и это сработало (может ли это быть причиной?) ... спасибо за ваша помощь очень ценна, я застрял с этим в течение 3 дней, некуда идти, ваш код направлен правильно .... наконец решен

tintin 26.04.2022 07:27

Другие вопросы по теме