changeset 85:701a0fba8aab

Implementing CloudKit
author Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com>
date Tue, 26 Jan 2021 17:24:30 +0100
parents 6ae5b2191c54
children 1850681a3715
files LazyBear.xcodeproj/project.pbxproj LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate lazybear/CloudKitManager.swift lazybear/Core Data/Persistence.swift lazybear/IexApi.swift lazybear/LazyBear.entitlements lazybear/LazyBearApp.swift lazybear/Persistence.swift lazybear/Tests/Test.swift
diffstat 9 files changed, 173 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/LazyBear.xcodeproj/project.pbxproj	Mon Jan 25 13:07:37 2021 +0100
+++ b/LazyBear.xcodeproj/project.pbxproj	Tue Jan 26 17:24:30 2021 +0100
@@ -8,14 +8,16 @@
 
 /* Begin PBXBuildFile section */
 		95002580256D17D9008FFD28 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9500257F256D17D9008FFD28 /* StoreKit.framework */; };
+		95078FD125BF4E640004FA75 /* CloudKitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95078FD025BF4E640004FA75 /* CloudKitManager.swift */; };
 		950B79F625B1CB7A00E5DB5B /* CompanyList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 950B79F525B1CB7A00E5DB5B /* CompanyList.swift */; };
 		952498B625BB47A700B00E22 /* LatestPriceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952498B525BB47A700B00E22 /* LatestPriceModel.swift */; };
 		9537923625BDF85D0001F82B /* GoogleApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9537923525BDF85D0001F82B /* GoogleApi.swift */; };
 		9537924A25BDFCD70001F82B /* LoadImageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9537924925BDFCD70001F82B /* LoadImageTest.swift */; };
 		954D992525A2123B001F7F60 /* HistoricalPricesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954D992425A2123B001F7F60 /* HistoricalPricesModel.swift */; };
 		954D996D25A2461B001F7F60 /* SwiftUICharts in Frameworks */ = {isa = PBXBuildFile; productRef = 954D996C25A2461B001F7F60 /* SwiftUICharts */; };
-		954D997125A253A9001F7F60 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954D997025A253A9001F7F60 /* Config.swift */; };
 		95612C512598D48200F7698F /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95612C4F2598D48200F7698F /* SearchBar.swift */; };
+		95621AD925BF2EDB00BB17FC /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95621AD825BF2EDB00BB17FC /* CloudKit.framework */; };
+		95621ADB25BF32E200BB17FC /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95621ADA25BF32E200BB17FC /* Test.swift */; };
 		95700BC625BD9D12009CEEFE /* IexApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95700BC525BD9D12009CEEFE /* IexApi.swift */; };
 		95AB4A7A259DCBAE0064C9C1 /* ReadJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */; };
 		95AB4A7D259DCC0C0064C9C1 /* CompanyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */; };
@@ -47,13 +49,16 @@
 /* Begin PBXFileReference section */
 		95002578256D1564008FFD28 /* Configuration.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = Configuration.storekit; sourceTree = "<group>"; };
 		9500257F256D17D9008FFD28 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
+		95078FD025BF4E640004FA75 /* CloudKitManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CloudKitManager.swift; path = LazyBear/CloudKitManager.swift; sourceTree = SOURCE_ROOT; };
 		950B79F525B1CB7A00E5DB5B /* CompanyList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyList.swift; sourceTree = "<group>"; };
 		952498B525BB47A700B00E22 /* LatestPriceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LatestPriceModel.swift; path = lazybear/Models/LatestPriceModel.swift; sourceTree = SOURCE_ROOT; };
 		9537923525BDF85D0001F82B /* GoogleApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GoogleApi.swift; path = lazybear/GoogleApi.swift; sourceTree = SOURCE_ROOT; };
 		9537924925BDFCD70001F82B /* LoadImageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LoadImageTest.swift; path = lazybear/Tests/LoadImageTest.swift; sourceTree = SOURCE_ROOT; };
 		954D992425A2123B001F7F60 /* HistoricalPricesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = HistoricalPricesModel.swift; path = lazybear/Models/HistoricalPricesModel.swift; sourceTree = SOURCE_ROOT; };
-		954D997025A253A9001F7F60 /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Config.swift; path = lazybear/Config.swift; sourceTree = SOURCE_ROOT; };
 		95612C4F2598D48200F7698F /* SearchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; };
+		95621AD725BF2EC500BB17FC /* LazyBear.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LazyBear.entitlements; sourceTree = "<group>"; };
+		95621AD825BF2EDB00BB17FC /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
+		95621ADA25BF32E200BB17FC /* Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Test.swift; path = lazybear/Tests/Test.swift; sourceTree = SOURCE_ROOT; };
 		95700BC525BD9D12009CEEFE /* IexApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = IexApi.swift; path = lazybear/IexApi.swift; sourceTree = SOURCE_ROOT; };
 		95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReadJson.swift; path = lazybear/Functions/ReadJson.swift; sourceTree = SOURCE_ROOT; };
 		95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompanyModel.swift; path = lazybear/Models/CompanyModel.swift; sourceTree = SOURCE_ROOT; };
@@ -66,7 +71,7 @@
 		95B395A425BDF42E009A7EB0 /* companies.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = companies.json; path = lazybear/Data/companies.json; sourceTree = SOURCE_ROOT; };
 		95C28AB525BC45CF0033D16A /* ChartStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ChartStyle.swift; path = lazybear/Functions/ChartStyle.swift; sourceTree = SOURCE_ROOT; };
 		95C28AB825BC46250033D16A /* ScalateChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScalateChart.swift; path = lazybear/Functions/ScalateChart.swift; sourceTree = SOURCE_ROOT; };
-		95D1BF4825ADCF7700E5D063 /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Persistence.swift; path = "LazyBear/Core Data/Persistence.swift"; sourceTree = SOURCE_ROOT; };
+		95D1BF4825ADCF7700E5D063 /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Persistence.swift; path = LazyBear/Persistence.swift; sourceTree = SOURCE_ROOT; };
 		95E0287A25B88F3C00020CF2 /* FormDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FormDescription.swift; path = lazybear/Models/FormDescription.swift; sourceTree = SOURCE_ROOT; };
 		95E4119125BEC56F00A9C23F /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = "<group>"; };
 		95E4119525BEC9DD00A9C23F /* TestViewBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestViewBuilder.swift; path = lazybear/Tests/TestViewBuilder.swift; sourceTree = SOURCE_ROOT; };
@@ -89,6 +94,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				95E4118F25BEC35D00A9C23F /* SDWebImageSwiftUI in Frameworks */,
+				95621AD925BF2EDB00BB17FC /* CloudKit.framework in Frameworks */,
 				95002580256D17D9008FFD28 /* StoreKit.framework in Frameworks */,
 				954D996D25A2461B001F7F60 /* SwiftUICharts in Frameworks */,
 			);
@@ -100,6 +106,7 @@
 		9500257E256D17D9008FFD28 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				95621AD825BF2EDB00BB17FC /* CloudKit.framework */,
 				9500257F256D17D9008FFD28 /* StoreKit.framework */,
 			);
 			name = Frameworks;
@@ -110,6 +117,7 @@
 			children = (
 				9537924925BDFCD70001F82B /* LoadImageTest.swift */,
 				95E4119525BEC9DD00A9C23F /* TestViewBuilder.swift */,
+				95621ADA25BF32E200BB17FC /* Test.swift */,
 			);
 			path = Tests;
 			sourceTree = "<group>";
@@ -185,12 +193,13 @@
 		95B04EB125212369000AD27F /* LazyBear */ = {
 			isa = PBXGroup;
 			children = (
-				95D1BF4E25ADD2BA00E5D063 /* Core Data */,
+				95621AD725BF2EC500BB17FC /* LazyBear.entitlements */,
 				95B04EB62521236A000AD27F /* Assets.xcassets */,
 				95B04EBB2521236A000AD27F /* Info.plist */,
 				95002578256D1564008FFD28 /* Configuration.storekit */,
 				95F7CAF425ADC7B7009E0E7C /* LazyBear.xcdatamodeld */,
-				954D997025A253A9001F7F60 /* Config.swift */,
+				95D1BF4825ADCF7700E5D063 /* Persistence.swift */,
+				95078FD025BF4E640004FA75 /* CloudKitManager.swift */,
 				95700BC525BD9D12009CEEFE /* IexApi.swift */,
 				9537923525BDF85D0001F82B /* GoogleApi.swift */,
 				95B04EB225212369000AD27F /* LazyBearApp.swift */,
@@ -204,14 +213,6 @@
 			path = LazyBear;
 			sourceTree = "<group>";
 		};
-		95D1BF4E25ADD2BA00E5D063 /* Core Data */ = {
-			isa = PBXGroup;
-			children = (
-				95D1BF4825ADCF7700E5D063 /* Persistence.swift */,
-			);
-			path = "Core Data";
-			sourceTree = "<group>";
-		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -298,6 +299,7 @@
 				95E411BE25BEEA6C00A9C23F /* WatchlistRow.swift in Sources */,
 				95E411A325BEDDC400A9C23F /* WatchlistCompany+CoreDataProperties.swift in Sources */,
 				950B79F625B1CB7A00E5DB5B /* CompanyList.swift in Sources */,
+				95078FD125BF4E640004FA75 /* CloudKitManager.swift in Sources */,
 				95B04EB525212369000AD27F /* ContentView.swift in Sources */,
 				95AB4A90259DD66D0064C9C1 /* CompanyRow.swift in Sources */,
 				95F6C30125BAEC8B003CF389 /* CompanyView.swift in Sources */,
@@ -311,12 +313,12 @@
 				9537923625BDF85D0001F82B /* GoogleApi.swift in Sources */,
 				95C28AB625BC45CF0033D16A /* ChartStyle.swift in Sources */,
 				9537924A25BDFCD70001F82B /* LoadImageTest.swift in Sources */,
-				954D997125A253A9001F7F60 /* Config.swift in Sources */,
 				95C28AB925BC46250033D16A /* ScalateChart.swift in Sources */,
 				95E411B625BEE84E00A9C23F /* Stock.swift in Sources */,
 				954D992525A2123B001F7F60 /* HistoricalPricesModel.swift in Sources */,
 				95E411A725BEE03000A9C23F /* Watchlist.swift in Sources */,
 				95E411BA25BEEA4400A9C23F /* Title.swift in Sources */,
+				95621ADB25BF32E200BB17FC /* Test.swift in Sources */,
 				95F7CAF625ADC7B7009E0E7C /* LazyBear.xcdatamodeld in Sources */,
 				95E4119625BEC9DD00A9C23F /* TestViewBuilder.swift in Sources */,
 			);
@@ -446,7 +448,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
-				CODE_SIGN_ENTITLEMENTS = "";
+				CODE_SIGN_ENTITLEMENTS = LazyBear/LazyBear.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 4;
 				DEVELOPMENT_ASSET_PATHS = LazyBear/Assets.xcassets;
@@ -473,7 +475,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
-				CODE_SIGN_ENTITLEMENTS = "";
+				CODE_SIGN_ENTITLEMENTS = LazyBear/LazyBear.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 4;
 				DEVELOPMENT_ASSET_PATHS = LazyBear/Assets.xcassets;
Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lazybear/CloudKitManager.swift	Tue Jan 26 17:24:30 2021 +0100
@@ -0,0 +1,39 @@
+//
+//  CloudKitManager.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 25/1/21.
+//
+
+import SwiftUI
+import CloudKit
+
+class CloudKitManager {
+    func query(recordType: String, recordName: String) {  // recordType = "Database", e.g "API"
+        let publicDatabase = CKContainer.default().privateCloudDatabase
+        
+        // Query arguments
+        let recordID = CKRecord.ID(recordName: recordName)  // e.g iexApiProduction
+        let predicate = NSPredicate(format: "recordID = %@", recordID)
+        let query = CKQuery(recordType: recordType, predicate: predicate)
+        
+        //query.sortDescriptors = [NSSortDescriptor(key: "name", ascending: false)]
+        
+        // Query begins
+        publicDatabase.perform(query, inZoneWith: nil) { (results, error) in
+            if error != nil {
+                print("CloudKit query went wrong")
+                print(error!.localizedDescription)
+
+            } else {
+
+                if let results = results {
+                    print("Succesfull CloudKit query")
+                    
+                    // Results
+                    print(results as Array)
+                }
+            }
+        }
+    }
+}
--- a/lazybear/Core Data/Persistence.swift	Mon Jan 25 13:07:37 2021 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-//
-//  Persistence.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 12/1/21.
-//
-
-import CoreData
-
-struct PersistenceController {
-    static let shared = PersistenceController()
-
-    static var preview: PersistenceController = {
-        let result = PersistenceController(inMemory: true)
-        let viewContext = result.container.viewContext
-        for _ in 0..<13 {
-            let newItem = WatchlistCompany(context: viewContext)
-            newItem.symbol = String()
-            newItem.exchange = String()
-            newItem.exchangeSuffix = String()
-            newItem.exchangeName = String()
-            newItem.name = String()
-            newItem.date = String()
-            newItem.type = String()
-            newItem.iexId = String()
-            newItem.region = String()
-            newItem.currency = String()
-            newItem.isEnabled = Bool()
-            newItem.figi = String()
-            newItem.cik = String()
-            newItem.lei = String()
-        }
-        do {
-            try viewContext.save()
-        } catch {
-            // Replace this implementation with code to handle the error appropriately.
-            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
-            let nsError = error as NSError
-            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
-        }
-        return result
-    }()
-
-    let container: NSPersistentContainer
-
-    init(inMemory: Bool = false) {
-        container = NSPersistentContainer(name: "LazyBear")
-        if inMemory {
-            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
-        }
-        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
-            if let error = error as NSError? {
-                // Replace this implementation with code to handle the error appropriately.
-                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
-
-                /*
-                Typical reasons for an error here include:
-                * The parent directory does not exist, cannot be created, or disallows writing.
-                * The persistent store is not accessible, due to permissions or data protection when the device is locked.
-                * The device is out of space.
-                * The store could not be migrated to the current model version.
-                Check the error message to determine what the actual problem was.
-                */
-                fatalError("Unresolved error \(error), \(error.userInfo)")
-            }
-        })
-    }
-}
--- a/lazybear/IexApi.swift	Mon Jan 25 13:07:37 2021 +0100
+++ b/lazybear/IexApi.swift	Tue Jan 26 17:24:30 2021 +0100
@@ -8,21 +8,6 @@
 import SwiftUI
 
 struct IexApi {
-    enum BaseURL {
-        case sandbox
-        case production
-        
-        var path: (String, String) {
-            let token = Token()
-            switch self {
-            case .sandbox:
-                return ("https://sandbox.iexapis.com", token.sandbox)
-            case .production:
-                return ("https://cloud.iexapis.com", token.production)
-            }
-        }
-    }
-
     enum Version {
         case stable
         
@@ -76,17 +61,16 @@
     
     
     // Create URL
-    func getURL(baseURL: BaseURL, version: Version, stock: Stock, endpoint: Endpoint, range: Range, parameters: Parameters) -> String {
-        let (baseURL, token) = baseURL.path
+    func getURL(version: Version, stock: Stock, endpoint: Endpoint, range: Range, parameters: Parameters) -> String {
         let version = version.path
         let stock = stock.path
         let endpoint = endpoint.path
         let range = range.path
         let parameters = parameters.path
         
-        let url = "\(baseURL)\(version)\(stock)\(endpoint)\(range)\(parameters)&token=\(token)"
+        let path = "\(version)\(stock)\(endpoint)\(range)\(parameters)&token="
         
-        return url
+        return path
         
     }
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lazybear/LazyBear.entitlements	Tue Jan 26 17:24:30 2021 +0100
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>aps-environment</key>
+	<string>development</string>
+	<key>com.apple.developer.icloud-container-identifiers</key>
+	<array>
+		<string>iCloud.dennis.LazyBear</string>
+	</array>
+	<key>com.apple.developer.icloud-services</key>
+	<array>
+		<string>CloudKit</string>
+	</array>
+	<key>com.apple.developer.ubiquity-kvstore-identifier</key>
+	<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
+</dict>
+</plist>
--- a/lazybear/LazyBearApp.swift	Mon Jan 25 13:07:37 2021 +0100
+++ b/lazybear/LazyBearApp.swift	Tue Jan 26 17:24:30 2021 +0100
@@ -13,7 +13,7 @@
 
     var body: some Scene {
         WindowGroup {
-            ContentView()
+            Test()
                 .environment(\.managedObjectContext, persistenceController.container.viewContext)
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lazybear/Persistence.swift	Tue Jan 26 17:24:30 2021 +0100
@@ -0,0 +1,68 @@
+//
+//  Persistence.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 12/1/21.
+//
+
+import CoreData
+
+struct PersistenceController {
+    static let shared = PersistenceController()
+
+    static var preview: PersistenceController = {
+        let result = PersistenceController(inMemory: true)
+        let viewContext = result.container.viewContext
+        for _ in 0..<13 {
+            let newItem = WatchlistCompany(context: viewContext)
+            newItem.symbol = String()
+            newItem.exchange = String()
+            newItem.exchangeSuffix = String()
+            newItem.exchangeName = String()
+            newItem.name = String()
+            newItem.date = String()
+            newItem.type = String()
+            newItem.iexId = String()
+            newItem.region = String()
+            newItem.currency = String()
+            newItem.isEnabled = Bool()
+            newItem.figi = String()
+            newItem.cik = String()
+            newItem.lei = String()
+        }
+        do {
+            try viewContext.save()
+        } catch {
+            // Replace this implementation with code to handle the error appropriately.
+            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
+            let nsError = error as NSError
+            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
+        }
+        return result
+    }()
+
+    let container: NSPersistentContainer
+
+    init(inMemory: Bool = false) {
+        container = NSPersistentContainer(name: "LazyBear")
+        if inMemory {
+            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
+        }
+        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
+            if let error = error as NSError? {
+                // Replace this implementation with code to handle the error appropriately.
+                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
+
+                /*
+                Typical reasons for an error here include:
+                * The parent directory does not exist, cannot be created, or disallows writing.
+                * The persistent store is not accessible, due to permissions or data protection when the device is locked.
+                * The device is out of space.
+                * The store could not be migrated to the current model version.
+                Check the error message to determine what the actual problem was.
+                */
+                fatalError("Unresolved error \(error), \(error.userInfo)")
+            }
+        })
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lazybear/Tests/Test.swift	Tue Jan 26 17:24:30 2021 +0100
@@ -0,0 +1,26 @@
+//
+//  TestCloudKit.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 25/1/21.
+//
+
+import SwiftUI
+
+struct Test: View {
+    let cloudKit = CloudKitManager()
+    
+    var body: some View {
+        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
+            .onAppear {
+                cloudKit.query(recordType: "API")
+            }
+    }
+}
+
+struct Test_Previews: PreviewProvider {
+    static var previews: some View {
+        Test()
+    }
+}
+