Search code examples
iosswiftswiftuiurlsessionjsondecoder

How to send tokens with url using URLSession and decode it in SwiftUI


I need to send tokens with a get url in my iOS app and use its response in my view. One can fetch api through the following code:

final class IMDBAPI{

// function to get data from the api
func getDataForPageNr(page: Int, completion: @escaping (PageData) -> ()){
    
    // check if page argument in the URL is a positive number
    guard page >= 1 else{ return }
    
    // create the URL
    if let url = URL(string: "http://www.omdbapi.com/?s=Batman&page=\(page)&apikey=eeefc96f"){
        // start URL session
        URLSession.shared.dataTask(with: url){ data, response, error in
            // if you get a data response
            if let data = data{
                do{
                    // decode the JSON to the PageData object
                    let result = try JSONDecoder().decode(PageData.self, from: data)
                    
                    // we are changing the UI dynamically here, you have to do that on the main thread in SwiftUI
                    DispatchQueue.main.async {
                        // use the completion handler and pass the result
                        completion(result)
                    }
                    
                }
                // here handle errors when decoding of JSON fails
                catch let error{
                    print(error)
                }
            }
        }.resume()
    }
}

}

the above code works perfectly if one doesn't have tokens to send In my case I have the following api: https://contributorapi.yogpathwellness.com/ProfileMaster/Dashboard/VID_307 and the following tokens to send "Token": "MkpHS3Ftei9kWWRMM3k3eGpaQnNhR2xUK0h2NnI0MlZXV3ZIbjVJY0pjOD0jMjAyMDEyMDEy" "DeviceId": "202012012"

the response I shall be getting from the api

{
"data": {
    "Cid": "VID_307",
    "Fullname": "Yog maya",
    "LiveClass": [
        {
            "author": "",
            "class_starttime": "",
            "classid": "",
            "image": "https://storage.googleapis.com/yoga_data/DefaultImage.gif",
            "starts_in": "",
            "title": ""
        }
    ],
    "Skill": "",
    "Status": "Lead",
    "achievment_description": "",
    "certificate": "0",
    "classes": [
        {
            "class_name": "",
            "consultant": "0",
            "image": "https://storage.googleapis.com/yogpath_vendor_data/No_Image_Available.jpg",
            "live_classes": "0",
            "ratings": "",
            "total_video": "0",
            "users": "0"
        }
    ],
    "descriptions": "",
    "experience": "20",
    "followers": "0",
    "isLive": false,
    "latest_video": [
        {
            "Duration": null,
            "Title": "",
            "comment": "0",
            "content_id": null,
            "description": "",
            "image": "https://storage.googleapis.com/yogpath_vendor_data/No_Image_Available.jpg",
            "like": "0",
            "name": "",
            "thumbnail": "https://storage.googleapis.com/yogpath_vendor_data/No_Image_Available.jpg",
            "time": "",
            "vendorprofile": "https://storage.googleapis.com/yogpath_vendor_data/No_Image_Available.jpg",
            "videourl": "",
            "view": "0",
            "viewers": []
        }
    ],
    "live_classes": "0",
    "no_of_video": "0",
    "random_yoga": [
        {
            "image": "",
            "location": "",
            "name": "",
            "rating": "",
            "users": "0"
        }
    ],
    "rating": "",
    "reviews": "0",
    "schedule": [
        {
            "Date": "",
            "DateDynamic": [
                {
                    "name": "",
                    "subscriber": [
                        {
                            "image": "",
                            "name": "",
                            "userId": ""
                        }
                    ],
                    "time_range": "",
                    "type": ""
                }
            ]
        }
    ],
    "selfie": "https://storage.googleapis.com/yogpath_vendor_data/No_Image_Available.jpg",
    "sessions": "0",
    "successful_ot": "0",
    "total_patients": "0",
    "view": "0"
},
"message": "Success",
"status": true

}

I need to store the response in the following Struct:

    struct InstructorDetails: Codable {
    let data: [Data1]
    let message: String
    let status: Bool
}
struct Data1: Codable {
    let Cid: String
    let Fullname: String
    let LiveClass: [LiveClass]
    let Skill: String
    let Status: String
    let achievement_description: String
    let certificate: String
    let classes: [Classes]
    let descriptions: String
    let experience: String
    let followers: String
    let isLive: String
    let latest_video: [LatestVideo]
    let live_classes: String
    let no_of_video: String
    let random_yoga: [RandomYoga]
    let rating: String
    let reviews: String
    let schedule: [Schedule]
    let selfie: String
    let sessions: String
    let successful_ot: String
    let total_patients: String
    let views: String
}

struct LiveClass: Codable {
    let author: String
    let class_starttime: String
    let classid: String?
    let image: String?
    let starts_in: String
    let title: String?
}
struct Classes: Codable {
    let class_name: String
    let consultant: String
    let image: String
    let live_classes: String
    let ratings: String
    let total_video: String
    let users: String
}

struct LatestVideo: Codable {
    let comment: String
    let image: String
    let like: String
    let name: String
    let thumbnail: String
    let time: String
    let venorprofile: String
    let videourl: String
    let views: String
    let viewers: [Int]?
}

struct RandomYoga: Codable {
    let image: String
    let location: String
    let name: String
    let rating: String
    let users: String
}
struct Schedule: Codable {
    let date: String?
    let dateDynamic: [DateDynamic]
    enum CodingKeys: String, CodingKey{
        case date = "Date"
        case dateDynamic = "DateDynamic"
    }
}
struct DateDynamic: Codable {
    let name: String
    let subscriber: [Subscriber]
    let time_range: String?
    let type: String?
}
struct Subscriber: Codable {
    let image: String?
    let name: String?
    let userId: String?
}

I am trying to have a similar approach like this short project(working): https://github.com/themacbookaircoder/IMDB-SwiftUI

Below is my view where I am trying to use it in(failed attempt):

import SwiftUI
import Alamofire
import Kingfisher
import SwiftUIX

struct ProfileTabView: View {
    
    @State var rating = 3.0
    
    @State var followers  = "5000"
    @State var videos = "254"
    
    @State var liveClasses = "254"
    @State var sessions = "254"
    
    @State var imageName = ""
    @State var reviews = "4000"
    
    @State var views: Int = 2382
    @State var liveClass: [String] = [""]
    
    @State private var instructorDetails = InstructorDetails(data: [], message: "this", status: false)
    
    var gridItemLayout = [GridItem(.fixed(20)), GridItem(.fixed(20)), GridItem(.fixed(20))]
    
    var body: some View {
        VStack {
            ScrollView {
                VStack {
                    //print(instructorDetails.message)
                    Group {
                        ZStack {
                            Image("default-profile")
//                            Image("\(imageName)")  //default-profile
//                                .resizable()
//                                .frame(width: percentWidth(percentage: 100), height: percentHeight(percentage: 100))
                           
                            HStack {
                                VStack {
                                    HStack {
                                        Text("Live  \(instructorDetails.message)")
                                            .padding(3)
                                            .padding([.leading, .trailing], 5)
                                            .background(Color.red)
                                            .foregroundColor(Color.white)

                                        HStack {
                                            Image("eyeforteen")
                                                .resizable()
                                                .frame(width: 20, height: 15)
                                            Text("\(views)")
                                                .foregroundColor(.white)
                                                .font(Font.custom(FontName.normal, size: 17))
                                        }
                                        .padding(3)
                                        .padding([.leading, .trailing], 5)
                                        .background(Color(red: 0/255, green: 0/255, blue: 0/255, opacity: 0.2))
                                    }
                                    .padding()

                                    Spacer()
                                }
                                Spacer()
                                VStack(spacing: 1) {
                                    Text("\(followers) Followers")
                                        .foregroundColor(.white)
                                        .font(Font.custom(FontName.normal, size: 17))
                                        .padding(5)
                                    Text("\(reviews) Reviews")
                                        .foregroundColor(.white)
                                        .font(Font.custom(FontName.normal, size: 17))
                                        .padding(5)

                                    Button(action: {
                                        print("button pressed \(instructorDetails.message)")

                                    }) {
                                        ZStack {
                                            Image("blue-rect")
                                                .renderingMode(.original)
                                                .resizable()
                                                .frame(width: 120, height: 45)
                                            Text("Follow")
                                                .foregroundColor(.white)
                                                .font(Font.custom(FontName.bold, size: 20))
                                        }
                                    }
                                    .padding(5)
                                    Spacer()
                                }
                            }
                            .padding(.top, 35)

                        }
                        
           

                           

                    
                            
                                    
                                    HStack {
                                        LazyVGrid(columns: gridItemLayout, spacing: 0) {
                                            ForEach(viewsArr, id: \.self) { registerData in
                                                Image("avatar")
                                                    .resizable()
                                                    .frame(width: 30, height: 30)
                                                    .scaledToFill()
                                                    .cornerRadius(15)
                                            }
                                        }
                                    }
                                    
                                    Text("999+ views")
                                        .foregroundColor(.systemGray)
                                        .font(Font.custom(FontName.normal, size: 12))
                                }
                                
                                ZStack {
                                    RoundedRectangle(cornerRadius: 15)
                                        .shadow(color: .gray, radius: 3, x: -2, y: 2)
                                        .foregroundColor(Color.clear)
                                        .padding(1)
                                    
                                    VStack {
                                        Image("demoImg")
                                            .resizable()
                                            .frame(width: percentWidth(percentage: 95), 
                                    }
                                    
                                    VStack {
                                        HStack {
                                            HStack {
                                                Image("demoImg")
                                                    .resizable()
                                                    .frame(width: 35, height: 35)
                                                    .cornerRadius(35/2)
                                                
                                                VStack(alignment: .leading) {
                                                    HStack {
                                                        Text("Linda")
                                                            .foregroundColor(.white)
                                                           
                                                    }
                                                    
                                                    HStack {
                                                        Text("2 hours ago")
                                                            .foregroundColor(.white)
                                                            .font(Font.custom(FontName.normal, size: 15))
                                                    }
                                                    .padding(.trailing, 10)
                                                }
                                            }
                                            
                                            .clipShape(Capsule())
                                            Spacer()
                                        }
                                        .padding()
                                        Spacer()
                                    }
                                }
                                HStack {
                                    HStack {
                                        Image("heartVid")
                                            .resizable()
                                            .frame(width: 22, height: 22)
                                        Text("1242")
                                            .foregroundColor(.systemGray)
                                            .font(Font.custom(FontName.normal, size: 12))
                                    }
                                    
                                    HStack {
                                        Image("commentVid")
                                            .resizable()
                                            .frame(width: 22, height: 22)
                                        Text("1242")
                                            .foregroundColor(.systemGray)
                                            .font(Font.custom(FontName.normal, size: 12))
                                    }
                                    .padding(.leading, 20)
                                    Spacer()
                                    
                                    HStack {
                                        LazyVGrid(columns: gridItemLayout, spacing: 0) {
                                            ForEach(viewsArr, id: \.self) { registerData in
                                                Image("avatar")
                                                    .resizable()
                                                    .frame(width: 30, height: 30)
                                                    .scaledToFill()
                                                    .cornerRadius(15)
                                            }
                                        }
                                    }
                                    
                                    Text("999+ views")
                                        .foregroundColor(.systemGray)
                                        .font(Font.custom(FontName.normal, size: 12))
                                }
                            }
                            .frame(width: percentWidth(percentage: 90))
                            
                        }
                        .frame(width: percentWidth(percentage: 95))
                        
                    }
                    }
                Group {
                    Text("My Class").font(Font.custom(FontName.medium, size: 20)).padding(.trailing, percentWidth(percentage: 72))
                    VStack {
                        Image("barometer").resizable().frame(width: percentWidth(percentage: 100), height: percentHeight(percentage: 25), alignment: .leading)
                        HStack(alignment: .center, spacing: 8) {
                            Image("video").resizable().frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("100+").font(Font.custom(FontName.medium, size: 14))
                                Text("videos").font(Font.custom(FontName.medium, size: 10)).opacity(0.5)
                            }.padding(.trailing, 14)
                            
                            Image("liveClasses")
                                .resizable()
                                .frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("15+").font(Font.custom(FontName.medium, size: 14))
                                Text("live class").font(Font.custom(FontName.medium, size: 10)).opacity(0.5)
                            }.padding(.trailing, 14)
                            
                            Image("liveClasses")
                                .resizable()
                                .frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("78+").font(Font.custom(FontName.medium, size: 14))
                                Text("consultant").font(Font.custom(FontName.medium, size: 9)).opacity(0.5)
                            }.padding(.trailing, 14)
                            
                            Image("sessions")
                                .resizable()
                                .frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("2000+").font(Font.custom(FontName.medium, size: 10))
                                Text("users").font(Font.custom(FontName.medium, size: 10)).opacity(0.5)
                            }.padding(.trailing, 20)
                        }
                    }
                    VStack {
                        Image("barometer").resizable().frame(width: percentWidth(percentage: 100), height: percentHeight(percentage: 25), alignment: .leading)
                        HStack(alignment: .center, spacing: 8) {
                            Image("video").resizable().frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("100+").font(Font.custom(FontName.medium, size: 14))
                                Text("videos").font(Font.custom(FontName.medium, size: 10)).opacity(0.5)
                            }.padding(.trailing, 14)
                            
                            Image("liveClasses")
                                .resizable()
                                .frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("15+").font(Font.custom(FontName.medium, size: 14))
                                Text("live class").font(Font.custom(FontName.medium, size: 10)).opacity(0.5)
                            }.padding(.trailing, 14)
                            
                            Image("liveClasses")
                                .resizable()
                                .frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("78+").font(Font.custom(FontName.medium, size: 14))
                                Text("consultant").font(Font.custom(FontName.medium, size: 9)).opacity(0.5)
                            }.padding(.trailing, 14)
                            
                            Image("sessions")
                                .resizable()
                                .frame(width: percentWidth(percentage: 8), height: percentHeight(percentage: 4))
                            VStack {
                                Text("2000+").font(Font.custom(FontName.medium, size: 10))
                                Text("users").font(Font.custom(FontName.medium, size: 10)).opacity(0.5)
                            }.padding(.trailing, 20)
                        }
                    }
                    
                    
                    Text("My Schedule").font(Font.custom(FontName.medium, size: 18)).opacity(0.4).padding(.trailing, percentWidth(percentage: 70))
                    Text("Today , Mon, june 8").font(Font.custom(FontName.medium, size:18)).opacity(0.7).padding(.trailing, percentWidth(percentage: 50))
                    
                    ZStack {
                        RoundedRectangle(cornerRadius: 6)
                            .shadow(color: .gray, radius: 3, x: -4, y: 4)
                            .frame(width: percentWidth(percentage: 92), height: percentHeight(percentage: 20))
                            .foregroundColor(Color.blue).opacity(0.17)
                            .padding(5)
                        HStack {
                            
                    }
                }
                
                
            }
        }
        .onAppear {
                    //network.getUsers()
            getDataInstructor() {
                instructorDetails in
                self.instructorDetails = instructorDetails
            }
            //InstructorAPI()
//            InstructorAPI().getDataForInstructor{ (instructorDetails) in
//                self.instructorDetails = instructorDetails
                
            }
        
        .edgesIgnoringSafeArea(.all)
    }
    func getDataInstructor(completion: @escaping (InstructorDetails) -> ()){

        if let url = URL(string: "https://contributorapi.yogpathwellness.com/ProfileMaster/Dashboard/VID_307"){
            var urlRequest = URLRequest(url: url)
            urlRequest.setValue("MkpHS3Ftei9kWWRMM3k3eGpaQnNhR2xUK0h2NnI0MlZXV3ZIbjVJY0pjOD0jMjAyMDEyMDEy", forHTTPHeaderField: "Token")
            urlRequest.setValue("202012012", forHTTPHeaderField: "DeviceId")
            let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
                if let error = error {
                    print("Request error: ", error)
                    return
                }

                guard let response = response as? HTTPURLResponse else { return }
                
                if response.statusCode == 200 {
                    guard let data = data else { return }
                    do {
                        
                        print("User Data Respons\(data)")
//                        let decodedUsers = try JSONDecoder().decode([User].self, from: data)
//                        self.users = decodedUsers
                    }
                    DispatchQueue.main.async {
                        
                    }
                }
            }

            dataTask.resume()
        }
                                
        }
    }

I am able to get the user data in my Xcode log as: User Data Respons1444 bytes I am looking for a clean approach which decodes my data and feed that to the instructorDetails object(of InstructorDetails struct) An approach using Alamofire would also be welcomed.


Solution

  • Do you mean you want to send "Token" and "DeviceId" in your URLRequest?

    var apiRequest = URLRequest(url: URL(string: "your url link")!)
    apiRequest.httpMethod = "GET" 
    apiRequest.addValue("MkpHS3Ftei9kWWRMM3k3eGpaQnNhR2xUK0h2NnI0MlZXV3ZIbjVJY0pjOD0jMjAyMDEyMDEy", forHTTPHeaderField: "Token")
    apiRequest.addValue("202012012", forHTTPHeaderField: "DeviceId")
    apiRequest.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
    
    URLSession.shared.dataTask(with: apiUrlRequest){ data, response, error in
                //process the response
            }.resume()
    

    Difference of "addValue" and "setValue" here