changeset 337:31f2838b2de7

Improving API requests with DispatchGroup
author Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com>
date Thu, 01 Apr 2021 16:34:45 +0200
parents 6f904b166564
children 71a9c0e61783
files LazyBear.xcodeproj/project.pbxproj LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate LazyBear/Global Models/CompanyRowModel.swift LazyBear/Global Models/IntradayPricesModel.swift LazyBear/Global functions/GenericRequest.swift LazyBear/Global functions/Request.swift LazyBear/Resources/Phrases.json LazyBear/Views/Home/Helpers/TradingDatesItem.swift LazyBear/Views/Home/HomeView.swift LazyBear/Views/Home/Networking/HomeData.swift LazyBear/Views/Home/Networking/HomeModels.swift LazyBear/Views/Home/TradingDates.swift LazyBear/Views/Networking/HomeData.swift LazyBear/Views/Networking/SectorPerformanceModel.swift LazyBear/Views/Networking/TradingDatesModel.swift
diffstat 15 files changed, 245 insertions(+), 220 deletions(-) [+]
line wrap: on
line diff
--- a/LazyBear.xcodeproj/project.pbxproj	Wed Mar 31 20:42:44 2021 +0200
+++ b/LazyBear.xcodeproj/project.pbxproj	Thu Apr 01 16:34:45 2021 +0200
@@ -14,8 +14,9 @@
 		951566E72613A2B6007C0F36 /* TradingDates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951566E62613A2B6007C0F36 /* TradingDates.swift */; };
 		951566EA2613A37C007C0F36 /* TradingDatesItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951566E92613A37C007C0F36 /* TradingDatesItem.swift */; };
 		952045152610C7C600A76362 /* ConvertEpoch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952045142610C7C600A76362 /* ConvertEpoch.swift */; };
-		952045182610C83600A76362 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952045172610C83600A76362 /* Request.swift */; };
-		952045242610FD7F00A76362 /* CompanyRowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952045232610FD7F00A76362 /* CompanyRowModel.swift */; };
+		9523ED422615BDB2006D3D6F /* Phrases.json in Resources */ = {isa = PBXBuildFile; fileRef = 9523ED412615BDB2006D3D6F /* Phrases.json */; };
+		9523ED542615CB7F006D3D6F /* HomeData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9523ED532615CB7F006D3D6F /* HomeData.swift */; };
+		9523ED592615D1D8006D3D6F /* GenericRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9523ED582615D1D8006D3D6F /* GenericRequest.swift */; };
 		954D7EA7260BBA6600A13C50 /* WatchlistCompany+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954D7EA5260BBA6600A13C50 /* WatchlistCompany+CoreDataClass.swift */; };
 		954D7EA8260BBA6600A13C50 /* WatchlistCompany+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954D7EA6260BBA6600A13C50 /* WatchlistCompany+CoreDataProperties.swift */; };
 		954D7EC2260BE70C00A13C50 /* SwiftlySearch in Frameworks */ = {isa = PBXBuildFile; productRef = 954D7EC1260BE70C00A13C50 /* SwiftlySearch */; };
@@ -29,12 +30,9 @@
 		95672B9625DDA54700DCBE4A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95672B9525DDA54700DCBE4A /* Preview Assets.xcassets */; };
 		95672B9825DDA54700DCBE4A /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95672B9725DDA54700DCBE4A /* Persistence.swift */; };
 		95672B9B25DDA54800DCBE4A /* LazyBear.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 95672B9925DDA54800DCBE4A /* LazyBear.xcdatamodeld */; };
-		9585FE782614E5E60022CFD8 /* TradingDatesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9585FE772614E5E60022CFD8 /* TradingDatesModel.swift */; };
-		95893DC92613C421003698C5 /* HomeData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95893DC82613C421003698C5 /* HomeData.swift */; };
-		95893DCE2613C46B003698C5 /* SectorPerformanceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95893DCD2613C46B003698C5 /* SectorPerformanceModel.swift */; };
+		95893DCE2613C46B003698C5 /* HomeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95893DCD2613C46B003698C5 /* HomeModels.swift */; };
 		958A735225E0170900FD7ECA /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 958A735125E0170900FD7ECA /* CloudKit.framework */; };
 		95AD4A2D26078C1400498079 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AD4A2C26078C1400498079 /* ContentView.swift */; };
-		95BC3B4F261476FB00FC3A12 /* IntradayPricesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BC3B4E261476FB00FC3A12 /* IntradayPricesModel.swift */; };
 		95E745DA2614624500744A1E /* HomeDataPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E745D92614624500744A1E /* HomeDataPreview.swift */; };
 		95ECCA5D2612169200A67EFA /* LineShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95ECCA5C2612169200A67EFA /* LineShape.swift */; };
 		95ECCA60261216D500A67EFA /* LineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95ECCA5F261216D500A67EFA /* LineView.swift */; };
@@ -50,8 +48,9 @@
 		951566E62613A2B6007C0F36 /* TradingDates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TradingDates.swift; sourceTree = "<group>"; };
 		951566E92613A37C007C0F36 /* TradingDatesItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TradingDatesItem.swift; sourceTree = "<group>"; };
 		952045142610C7C600A76362 /* ConvertEpoch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConvertEpoch.swift; sourceTree = "<group>"; };
-		952045172610C83600A76362 /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = "<group>"; };
-		952045232610FD7F00A76362 /* CompanyRowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyRowModel.swift; sourceTree = "<group>"; };
+		9523ED412615BDB2006D3D6F /* Phrases.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = Phrases.json; sourceTree = "<group>"; };
+		9523ED532615CB7F006D3D6F /* HomeData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeData.swift; sourceTree = "<group>"; };
+		9523ED582615D1D8006D3D6F /* GenericRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericRequest.swift; sourceTree = "<group>"; };
 		954D7EA5260BBA6600A13C50 /* WatchlistCompany+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WatchlistCompany+CoreDataClass.swift"; sourceTree = "<group>"; };
 		954D7EA6260BBA6600A13C50 /* WatchlistCompany+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WatchlistCompany+CoreDataProperties.swift"; sourceTree = "<group>"; };
 		9550443926111B2B000E0BCB /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
@@ -66,13 +65,10 @@
 		95672B9725DDA54700DCBE4A /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = "<group>"; };
 		95672B9A25DDA54800DCBE4A /* LazyBear.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LazyBear.xcdatamodel; sourceTree = "<group>"; };
 		95672B9C25DDA54800DCBE4A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		9585FE772614E5E60022CFD8 /* TradingDatesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TradingDatesModel.swift; sourceTree = "<group>"; };
-		95893DC82613C421003698C5 /* HomeData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeData.swift; sourceTree = "<group>"; };
-		95893DCD2613C46B003698C5 /* SectorPerformanceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectorPerformanceModel.swift; sourceTree = "<group>"; };
+		95893DCD2613C46B003698C5 /* HomeModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeModels.swift; sourceTree = "<group>"; };
 		958A734E25E016FD00FD7ECA /* LazyBear.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LazyBear.entitlements; sourceTree = "<group>"; };
 		958A735125E0170900FD7ECA /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
 		95AD4A2C26078C1400498079 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
-		95BC3B4E261476FB00FC3A12 /* IntradayPricesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntradayPricesModel.swift; sourceTree = "<group>"; };
 		95E745D92614624500744A1E /* HomeDataPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeDataPreview.swift; sourceTree = "<group>"; };
 		95ECCA5C2612169200A67EFA /* LineShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineShape.swift; sourceTree = "<group>"; };
 		95ECCA5F261216D500A67EFA /* LineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineView.swift; sourceTree = "<group>"; };
@@ -110,11 +106,19 @@
 			isa = PBXGroup;
 			children = (
 				952045142610C7C600A76362 /* ConvertEpoch.swift */,
-				952045172610C83600A76362 /* Request.swift */,
+				9523ED582615D1D8006D3D6F /* GenericRequest.swift */,
 			);
 			path = "Global functions";
 			sourceTree = "<group>";
 		};
+		9523ED402615BD93006D3D6F /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				9523ED412615BDB2006D3D6F /* Phrases.json */,
+			);
+			path = Resources;
+			sourceTree = "<group>";
+		};
 		954D7E9D260BBA5200A13C50 /* Global Models */ = {
 			isa = PBXGroup;
 			children = (
@@ -122,8 +126,6 @@
 				950C36E7260FBB550081CF53 /* UserSettings+CoreDataProperties.swift */,
 				954D7EA5260BBA6600A13C50 /* WatchlistCompany+CoreDataClass.swift */,
 				954D7EA6260BBA6600A13C50 /* WatchlistCompany+CoreDataProperties.swift */,
-				952045232610FD7F00A76362 /* CompanyRowModel.swift */,
-				95BC3B4E261476FB00FC3A12 /* IntradayPricesModel.swift */,
 			);
 			path = "Global Models";
 			sourceTree = "<group>";
@@ -134,6 +136,7 @@
 				9550443926111B2B000E0BCB /* HomeView.swift */,
 				951566E62613A2B6007C0F36 /* TradingDates.swift */,
 				954D7EAF260BBBD500A13C50 /* Helpers */,
+				95893DC72613C410003698C5 /* Networking */,
 			);
 			path = Home;
 			sourceTree = "<group>";
@@ -183,6 +186,7 @@
 				95B1874925DDAC4D0068A364 /* Views */,
 				952045132610C7A200A76362 /* Global functions */,
 				954D7E9D260BBA5200A13C50 /* Global Models */,
+				9523ED402615BD93006D3D6F /* Resources */,
 				95201A36260CAD36007D5300 /* Tests */,
 				95672B9425DDA54700DCBE4A /* Preview Content */,
 			);
@@ -201,9 +205,8 @@
 		95893DC72613C410003698C5 /* Networking */ = {
 			isa = PBXGroup;
 			children = (
-				95893DC82613C421003698C5 /* HomeData.swift */,
-				95893DCD2613C46B003698C5 /* SectorPerformanceModel.swift */,
-				9585FE772614E5E60022CFD8 /* TradingDatesModel.swift */,
+				9523ED532615CB7F006D3D6F /* HomeData.swift */,
+				95893DCD2613C46B003698C5 /* HomeModels.swift */,
 			);
 			path = Networking;
 			sourceTree = "<group>";
@@ -230,7 +233,6 @@
 			children = (
 				951490572610BD3000BDEEB5 /* Welcome */,
 				954D7EAA260BBB0E00A13C50 /* Home */,
-				95893DC72613C410003698C5 /* Networking */,
 				95893DD22613CAB5003698C5 /* Global Helpers */,
 			);
 			path = Views;
@@ -316,6 +318,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				95672B9625DDA54700DCBE4A /* Preview Assets.xcassets in Resources */,
+				9523ED422615BDB2006D3D6F /* Phrases.json in Resources */,
 				95672B9325DDA54700DCBE4A /* Assets.xcassets in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -328,11 +331,11 @@
 			buildActionMask = 2147483647;
 			files = (
 				950C36E3260FB6180081CF53 /* HapticsManager.swift in Sources */,
+				9523ED592615D1D8006D3D6F /* GenericRequest.swift in Sources */,
 				95E745DA2614624500744A1E /* HomeDataPreview.swift in Sources */,
 				9550444926111FC9000E0BCB /* TopStockRow.swift in Sources */,
-				952045242610FD7F00A76362 /* CompanyRowModel.swift in Sources */,
+				9523ED542615CB7F006D3D6F /* HomeData.swift in Sources */,
 				9550444326111E7A000E0BCB /* SectorRow.swift in Sources */,
-				952045182610C83600A76362 /* Request.swift in Sources */,
 				95ECCA60261216D500A67EFA /* LineView.swift in Sources */,
 				9550443A26111B2B000E0BCB /* HomeView.swift in Sources */,
 				950C36E8260FBB550081CF53 /* UserSettings+CoreDataClass.swift in Sources */,
@@ -340,11 +343,8 @@
 				950C36E9260FBB550081CF53 /* UserSettings+CoreDataProperties.swift in Sources */,
 				954D7EA8260BBA6600A13C50 /* WatchlistCompany+CoreDataProperties.swift in Sources */,
 				951566E72613A2B6007C0F36 /* TradingDates.swift in Sources */,
-				95BC3B4F261476FB00FC3A12 /* IntradayPricesModel.swift in Sources */,
-				95893DC92613C421003698C5 /* HomeData.swift in Sources */,
-				95893DCE2613C46B003698C5 /* SectorPerformanceModel.swift in Sources */,
+				95893DCE2613C46B003698C5 /* HomeModels.swift in Sources */,
 				95672B8F25DDA54700DCBE4A /* LazyBearApp.swift in Sources */,
-				9585FE782614E5E60022CFD8 /* TradingDatesModel.swift in Sources */,
 				95ECCA5D2612169200A67EFA /* LineShape.swift in Sources */,
 				9550444C26111FED000E0BCB /* TopStockItem.swift in Sources */,
 				951566EA2613A37C007C0F36 /* TradingDatesItem.swift in Sources */,
Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- a/LazyBear/Global Models/CompanyRowModel.swift	Wed Mar 31 20:42:44 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-//
-//  CompanyRowModel.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 28/3/21.
-//
-
-import SwiftUI
-
-struct CompanyRowModel: Codable, Hashable {
-    var symbol: String
-    var companyName: String
-    var latestPrice: Double
-    var changePercent: Double
-}
--- a/LazyBear/Global Models/IntradayPricesModel.swift	Wed Mar 31 20:42:44 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-//
-//  IntradayPricesModel.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 31/3/21.
-//
-
-import SwiftUI
-
-// Model prepared with batch
-
-struct IntradayPricesArray: Codable {
-    var intradayPrices: [IntradayPricesModel]
-
-    // Change key name
-    private enum CodingKeys : String, CodingKey {
-           case intradayPrices = "intraday-prices"
-       }
-}
-
-struct IntradayPricesModel: Codable {
-    var open: Double?
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Global functions/GenericRequest.swift	Thu Apr 01 16:34:45 2021 +0200
@@ -0,0 +1,36 @@
+//
+//  GenericRequest.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 1/4/21.
+//
+
+import SwiftUI
+
+// Network request
+func genericRequest<T: Decodable>(url: String, model: T.Type, completion: @escaping (_ result: T) -> Void) {
+    // We take some model data T.Type
+    guard let url = URL(string: url) else {
+        print("Invalid URL")
+        return
+    }
+    let request = URLRequest(url: url)
+    URLSession.shared.dataTask(with: request) { data, response, error in
+        if let data = data {
+            do {
+                // Decode response with the model passed
+                let decodedResponse = try JSONDecoder().decode(model, from: data)
+                DispatchQueue.main.async {
+                    completion(decodedResponse)
+                }
+                return
+            } catch {
+                // Return error regarding the escaping code
+                print(error)
+            }
+        }
+        // Error with the request
+        print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
+    }
+    .resume()
+}
--- a/LazyBear/Global functions/Request.swift	Wed Mar 31 20:42:44 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-//
-//  Request.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 28/3/21.
-//
-
-import Foundation
-
-// Network request
-func request<T: Decodable>(url: String, model: T.Type, completion: @escaping (_ result: T) -> Void) {
-    // We take some model data T.Type
-    guard let url = URL(string: url) else {
-        print("Invalid URL")
-        return
-    }
-    let request = URLRequest(url: url)
-    URLSession.shared.dataTask(with: request) { data, response, error in
-        if let data = data {
-            do {
-                // Decode response with the model passed
-                let decodedResponse = try JSONDecoder().decode(model, from: data)
-                DispatchQueue.main.async {
-                    completion(decodedResponse)
-                }
-                return
-            } catch {
-                // Return error regarding the escaping code
-                print(error)
-            }
-        }
-        // Error with the request
-        print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
-    }
-    .resume()
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Resources/Phrases.json	Thu Apr 01 16:34:45 2021 +0200
@@ -0,0 +1,25 @@
+[
+    {
+        "funny": [
+            "Tomorrow is often the busiest day of the week",
+            "They shorted my stock, I shortened their lives",
+            "The stock market is still les volatile than most of my romantic relationships",
+            "Dear diary, today the stock market did not crash",
+            "If you want to trade in derivates, god bless you",
+            "When the market crash, just take the absolute value",
+            "I was losing money before the stock market crashed",
+            "The Lazybear of Wall Street",
+            "Can't lose your savings if you have no savings",
+            "Stonks",
+            "So you dont buy more when a stock goes down?",
+            "Hey the stock market is up AAAA It's down",
+            "Top 3 richest people: Musk, Bezos, not you",
+            "Oh no... my stock did what?",
+            "Are you a Redditor?",
+            "No I don't know what happened",
+            "Hey, Do you want some quantitative easing?",
+            "Money printer go Brrr",
+            "You have two cows. The State takes both of them and gives you the milk"
+        ]
+    }
+]
--- a/LazyBear/Views/Home/Helpers/TradingDatesItem.swift	Wed Mar 31 20:42:44 2021 +0200
+++ b/LazyBear/Views/Home/Helpers/TradingDatesItem.swift	Thu Apr 01 16:34:45 2021 +0200
@@ -29,18 +29,16 @@
                             .font(.title)
                             .fontWeight(.semibold)
                             .foregroundColor(Color("default"))
+                        
+                        Text(get(.year))
+                            .font(.caption)
+                            .fontWeight(.semibold)
                     }
                     
                     Spacer()
                     VStack {
-                        Text("US Markets open in regular hours")
+                        Text("US Markets are closed")
                             .fontWeight(.semibold)
-                        
-                        Text("Random funny phrase")
-                            .font(.caption)
-                            .fontWeight(.semibold)
-                            .multilineTextAlignment(.center)
-                            .opacity(0.6)
                     }
                     
                     Spacer()
--- a/LazyBear/Views/Home/HomeView.swift	Wed Mar 31 20:42:44 2021 +0200
+++ b/LazyBear/Views/Home/HomeView.swift	Thu Apr 01 16:34:45 2021 +0200
@@ -21,32 +21,36 @@
         let dueDate = Date()
     
     var body: some View {
-        NavigationView {
-            List {
-                SectorRow(sectorPerformance: homeData.sectorPerformance)
+        if homeData.showView {
+            NavigationView {
+                List {
+                    SectorRow(sectorPerformance: homeData.sectorPerformance)
+                        .listRowInsets(EdgeInsets())
+                        
+                    // Get keys of the dictionary list
+                    ForEach(homeData.list.keys.sorted(), id: \.self) { key in
+                        TopStockRow(key: key, list: homeData.list[key] ?? [CompanyRowModel](), intradayPricesDict: homeData.intradayPrices)
+                    }
                     .listRowInsets(EdgeInsets())
-                
-                // Get keys of the dictionary list
-                ForEach(homeData.list.keys.sorted(), id: \.self) { key in
-                    TopStockRow(key: key, list: homeData.list[key] ?? [CompanyRowModel](), intradayPricesDict: homeData.intradayPrices)
                 }
-                .listRowInsets(EdgeInsets())
-            }
-            .navigationTitle("\(dueDate, formatter: Self.taskDateFormat)")
-            .navigationBarTitleDisplayMode(.inline)
-            .navigationViewStyle(StackNavigationViewStyle())
-            .toolbar {
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    Button(action: { showTradingDates = true }) {
-                        Image(systemName: "calendar.badge.clock")
+                .onReceive(timer) {_ in homeData.request() }
+                .navigationTitle("\(dueDate, formatter: Self.taskDateFormat)")
+                .navigationBarTitleDisplayMode(.inline)
+                .navigationViewStyle(StackNavigationViewStyle())
+                .toolbar {
+                    ToolbarItem(placement: .navigationBarTrailing) {
+                        Button(action: { showTradingDates = true }) {
+                            Image(systemName: "calendar.badge.clock")
+                        }
                     }
                 }
             }
-        }
-        .onAppear { homeData.get() }
-        .onReceive(timer) {_ in homeData.get() }
-        .sheet(isPresented: $showTradingDates) {
-            TradingDates(stringDates: homeData.holidayDates)
+            .sheet(isPresented: $showTradingDates) {
+//                TradingDates(stringDates: homeData.holidayDates)
+            }
+        } else {
+            ProgressView()
+                .onAppear { homeData.request() }
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Networking/HomeData.swift	Thu Apr 01 16:34:45 2021 +0200
@@ -0,0 +1,85 @@
+//
+//  HomeData.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 1/4/21.
+//
+
+import SwiftUI
+
+class HomeData: ObservableObject {
+    @Published var showView = false
+    @Published var sectorPerformance = [SectorPerformanceModel]()
+    @Published var list = ["mostactive": [CompanyRowModel](), "gainers": [CompanyRowModel](), "losers": [CompanyRowModel]()]
+    @Published var intradayPrices = [String(): IntradayPricesArray(intradayPrices: [IntradayPricesModel(open: Double())])]
+    
+    private let baseUrl = Bundle.main.infoDictionary?["IEX_URL"] as? String ?? "Empty url"
+    private let apiKey = Bundle.main.infoDictionary?["IEX_API"] as? String ?? "Empty key"
+    
+    // Call this function to make the request
+    func request() {
+        let dispatchGroup = DispatchGroup()  // Start dispatch group
+        var url = String()
+        
+//      1. SECTOR PERFORMANCE REQUEST
+        url = "\(baseUrl)/stock/market/sector-performance?token=\(apiKey)"
+        print("Entering group: request Sector Performance")
+        dispatchGroup.enter()  // Enter group
+        
+        // API Request
+        genericRequest(url: url, model: [SectorPerformanceModel].self) {
+            self.sectorPerformance = $0
+            print("Leaving group: request Sector Performance")
+            dispatchGroup.leave()  // Leave group
+        }
+        
+//      2. LISTS REQUEST
+        var symbols = [String]()  // Know what symbols are in each list
+        for key in self.list.keys {
+            url = "\(baseUrl)/stock/market/collection/list?collectionName=\(key)&token=\(apiKey)"
+            print("Entering group: request list \(key)")
+            dispatchGroup.enter()  // Enter group
+            
+            // API Request
+            genericRequest(url: url, model: [CompanyRowModel].self) {
+                self.list[key] = $0
+                print("Leaving group: request list \(key)")
+                dispatchGroup.leave()
+                
+                // Append symbols requested to a list
+                if let companies = self.list[key] {  // Unwrap value
+                    for company in companies {  // Iterate inside the list through the companies
+                        symbols.append(company.symbol)
+                    }
+                }
+                
+                // Now that I have all the symbols I can request the intraday prices and save it to the @Published var
+                // First I have to concatenate the string to make the batch request
+                url = "\(self.baseUrl)/stock/market/batch?symbols="
+                for symbol in symbols {  // Concatenate symbol to the first part of the url
+                    if symbols.firstIndex(of: symbol) == 0 {
+                        url += symbol
+                    } else {
+                        url += ",\(symbol)"
+                   }
+                }
+            }
+        }
+        
+        // This will run after the ForLoop and if it was successful
+        dispatchGroup.notify(queue: .main) {
+            
+//           3. INTRADAY PRICES REQUEST
+            // Once the previous request are made, I can append the final part of the url and make the request
+            url = "\(url)&types=intraday-prices&token=\(self.apiKey)"
+            genericRequest(url: url, model: [String: IntradayPricesArray].self) {
+                self.intradayPrices = $0
+                
+                print("Request done successfully -> showing view")
+                self.showView = true
+            }
+        }
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Networking/HomeModels.swift	Thu Apr 01 16:34:45 2021 +0200
@@ -0,0 +1,43 @@
+//
+//  SectorPerformanceModel.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 30/3/21.
+//
+
+import SwiftUI
+
+struct SectorPerformanceModel: Codable, Hashable {
+    var name: String
+    var performance: Double
+    var lastUpdated: Int
+}
+
+
+struct CompanyRowModel: Codable, Hashable {
+    var symbol: String
+    var companyName: String
+    var latestPrice: Double
+    var changePercent: Double
+}
+
+
+// Model prepared with batch
+struct IntradayPricesArray: Codable {
+    var intradayPrices: [IntradayPricesModel]
+
+    // Change key name
+    private enum CodingKeys : String, CodingKey {
+           case intradayPrices = "intraday-prices"
+       }
+}
+
+struct IntradayPricesModel: Codable {
+    var open: Double?
+}
+
+
+struct TradingDatesModel: Codable {
+    var date: String
+
+}
--- a/LazyBear/Views/Home/TradingDates.swift	Wed Mar 31 20:42:44 2021 +0200
+++ b/LazyBear/Views/Home/TradingDates.swift	Thu Apr 01 16:34:45 2021 +0200
@@ -13,7 +13,7 @@
     var body: some View {
         NavigationView {
             ScrollView {
-                VStack(spacing: 30) {
+                VStack(spacing: 20) {
                     ForEach(getArrayOfDates(), id: \.self) { date in
                         TradingDatesItem(date: date)
                     }
--- a/LazyBear/Views/Networking/HomeData.swift	Wed Mar 31 20:42:44 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-//
-//  HomeData.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 30/3/21.
-//
-
-import SwiftUI
-
-class HomeData: ObservableObject {
-    @Published var sectorPerformance = [SectorPerformanceModel]()
-    @Published var list = ["mostactive": [CompanyRowModel](), "gainers": [CompanyRowModel](), "losers": [CompanyRowModel]()]
-    @Published var intradayPrices = [String(): IntradayPricesArray(intradayPrices: [IntradayPricesModel(open: Double())])]
-    @Published var holidayDates = [TradingDatesModel]()
-    
-    private let baseUrl = Bundle.main.infoDictionary?["IEX_URL"] as? String ?? "Empty url"
-    private let apiKey = Bundle.main.infoDictionary?["IEX_API"] as? String ?? "Empty key"
-    
-    // PRINCIPAL FUNCTION TO CALL
-    func get() {
-        // 1. Request sector performance
-        var url = "\(baseUrl)/stock/market/sector-performance?token=\(apiKey)"
-        request(url: url, model: [SectorPerformanceModel].self) { self.sectorPerformance = $0 }
-        
-        // 2. Request lists
-        var semaphore = 0
-        for key in self.list.keys {
-            url = "\(self.baseUrl)/stock/market/collection/list?collectionName=\(key)&token=\(self.apiKey)"
-            request(url: url, model: [CompanyRowModel].self) { self.list[key] = $0; semaphore += 1  // Finish modifying dictionary
-                
-                if semaphore == 3 {  // When dictionary is modified
-                    
-                    // 3. Request intraday prices
-                    var symbols = [String]()
-                    for key in self.list.keys {  // Iterate throught the list
-                        if let companies = self.list[key] {  // Unwrap value
-                            for company in companies {  // Iterate inside the list through the companies
-                                symbols.append(company.symbol)  // Append symbol
-                            }
-                        }
-                    }
-                    
-                    // Now that I have all the symbols I can request the intraday prices and save it to the @Published var
-                    // First I have to concatenate the string to make the batch request
-                    url = "\(self.baseUrl)/stock/market/batch?symbols="
-                    for symbol in symbols {  // Concatenate symbol to the first part of the url
-                        if symbols.firstIndex(of: symbol) == 0 {
-                            url += symbol
-                        } else {
-                            url += ",\(symbol)"
-                        }
-                    }
-
-                    // Once it's made, I can append the final part of the url and make the request
-                    url = "\(url)&types=intraday-prices&token=\(self.apiKey)"
-                    request(url: url, model: [String: IntradayPricesArray].self) { self.intradayPrices = $0 }
-                }
-            }
-        }
-        
-        // 4. Request trading and holiday days
-        url = "\(baseUrl)/ref-data/us/dates/holiday/next/30?token=\(apiKey)"
-        request(url: url, model: [TradingDatesModel].self) { self.holidayDates = $0 }
-    }
-}
--- a/LazyBear/Views/Networking/SectorPerformanceModel.swift	Wed Mar 31 20:42:44 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-//
-//  SectorPerformanceModel.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 30/3/21.
-//
-
-import SwiftUI
-
-struct SectorPerformanceModel: Codable, Hashable {
-    var name: String
-    var performance: Double
-    var lastUpdated: Int
-}
--- a/LazyBear/Views/Networking/TradingDatesModel.swift	Wed Mar 31 20:42:44 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-//
-//  TradingDatesModel.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 31/3/21.
-//
-
-import SwiftUI
-
-struct TradingDatesModel: Codable {
-    var date: String
-
-}