# HG changeset patch # User Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com> # Date 1611678270 -3600 # Node ID 701a0fba8aabaf0179bf98a2d9598188887335f5 # Parent 6ae5b2191c545a34d01c88e53c17227e10fe4d7f Implementing CloudKit diff -r 6ae5b2191c54 -r 701a0fba8aab LazyBear.xcodeproj/project.pbxproj --- 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 = ""; }; 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 = ""; }; 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 = ""; }; + 95621AD725BF2EC500BB17FC /* LazyBear.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LazyBear.entitlements; sourceTree = ""; }; + 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 = ""; }; 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 = ""; @@ -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 = ""; }; - 95D1BF4E25ADD2BA00E5D063 /* Core Data */ = { - isa = PBXGroup; - children = ( - 95D1BF4825ADCF7700E5D063 /* Persistence.swift */, - ); - path = "Core Data"; - sourceTree = ""; - }; /* 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; diff -r 6ae5b2191c54 -r 701a0fba8aab LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed diff -r 6ae5b2191c54 -r 701a0fba8aab lazybear/CloudKitManager.swift --- /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) + } + } + } + } +} diff -r 6ae5b2191c54 -r 701a0fba8aab lazybear/Core Data/Persistence.swift --- 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)") - } - }) - } -} diff -r 6ae5b2191c54 -r 701a0fba8aab lazybear/IexApi.swift --- 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 } diff -r 6ae5b2191c54 -r 701a0fba8aab lazybear/LazyBear.entitlements --- /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 @@ + + + + + aps-environment + development + com.apple.developer.icloud-container-identifiers + + iCloud.dennis.LazyBear + + com.apple.developer.icloud-services + + CloudKit + + com.apple.developer.ubiquity-kvstore-identifier + $(TeamIdentifierPrefix)$(CFBundleIdentifier) + + diff -r 6ae5b2191c54 -r 701a0fba8aab lazybear/LazyBearApp.swift --- 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) } } diff -r 6ae5b2191c54 -r 701a0fba8aab lazybear/Persistence.swift --- /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)") + } + }) + } +} diff -r 6ae5b2191c54 -r 701a0fba8aab lazybear/Tests/Test.swift --- /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() + } +} +