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.
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