From e70146018b60304425ab7edc70842213a32e5a1c Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 8 Feb 2026 18:36:34 +0100 Subject: [PATCH 1/6] Updated bundle identifiers for the app as well as unit and UI tests targets and also, improved the folder structure for the app target. --- .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/Contents.json | 0 .../Resources}/Assets.xcassets/Contents.json | 0 {Todos => App/Sources/App}/TodosApp.swift | 0 {Todos => App/Sources/Models}/Item.swift | 0 .../Sources/Views}/ContentView.swift | 0 Todos.xcodeproj/project.pbxproj | 103 +++++++----------- {TodosUITests => UITests}/TodosUITests.swift | 0 .../TodosUITestsLaunchTests.swift | 0 {TodosTests => UnitTests}/TodosTests.swift | 0 10 files changed, 37 insertions(+), 66 deletions(-) rename {Todos => App/Resources}/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename {Todos => App/Resources}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {Todos => App/Resources}/Assets.xcassets/Contents.json (100%) rename {Todos => App/Sources/App}/TodosApp.swift (100%) rename {Todos => App/Sources/Models}/Item.swift (100%) rename {Todos => App/Sources/Views}/ContentView.swift (100%) rename {TodosUITests => UITests}/TodosUITests.swift (100%) rename {TodosUITests => UITests}/TodosUITestsLaunchTests.swift (100%) rename {TodosTests => UnitTests}/TodosTests.swift (100%) diff --git a/Todos/Assets.xcassets/AccentColor.colorset/Contents.json b/App/Resources/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Todos/Assets.xcassets/AccentColor.colorset/Contents.json rename to App/Resources/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Todos/Assets.xcassets/AppIcon.appiconset/Contents.json b/App/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Todos/Assets.xcassets/AppIcon.appiconset/Contents.json rename to App/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Todos/Assets.xcassets/Contents.json b/App/Resources/Assets.xcassets/Contents.json similarity index 100% rename from Todos/Assets.xcassets/Contents.json rename to App/Resources/Assets.xcassets/Contents.json diff --git a/Todos/TodosApp.swift b/App/Sources/App/TodosApp.swift similarity index 100% rename from Todos/TodosApp.swift rename to App/Sources/App/TodosApp.swift diff --git a/Todos/Item.swift b/App/Sources/Models/Item.swift similarity index 100% rename from Todos/Item.swift rename to App/Sources/Models/Item.swift diff --git a/Todos/ContentView.swift b/App/Sources/Views/ContentView.swift similarity index 100% rename from Todos/ContentView.swift rename to App/Sources/Views/ContentView.swift diff --git a/Todos.xcodeproj/project.pbxproj b/Todos.xcodeproj/project.pbxproj index 3345345..71f1860 100644 --- a/Todos.xcodeproj/project.pbxproj +++ b/Todos.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 77; + objectVersion = 90; objects = { /* Begin PBXContainerItemProxy section */ @@ -30,19 +30,19 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ - 0296B2F22F38F8F7001C3BDB /* Todos */ = { + 0296B2F22F38F8F7001C3BDB /* App */ = { isa = PBXFileSystemSynchronizedRootGroup; - path = Todos; + path = App; sourceTree = ""; }; - 0296B3022F38F8F7001C3BDB /* TodosTests */ = { + 0296B3022F38F8F7001C3BDB /* UnitTests */ = { isa = PBXFileSystemSynchronizedRootGroup; - path = TodosTests; + path = UnitTests; sourceTree = ""; }; - 0296B30C2F38F8F7001C3BDB /* TodosUITests */ = { + 0296B30C2F38F8F7001C3BDB /* UITests */ = { isa = PBXFileSystemSynchronizedRootGroup; - path = TodosUITests; + path = UITests; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ @@ -50,24 +50,18 @@ /* Begin PBXFrameworksBuildPhase section */ 0296B2ED2F38F8F7001C3BDB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; 0296B2FC2F38F8F7001C3BDB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; 0296B3062F38F8F7001C3BDB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ @@ -75,9 +69,9 @@ 0296B2E72F38F8F7001C3BDB = { isa = PBXGroup; children = ( - 0296B2F22F38F8F7001C3BDB /* Todos */, - 0296B3022F38F8F7001C3BDB /* TodosTests */, - 0296B30C2F38F8F7001C3BDB /* TodosUITests */, + 0296B2F22F38F8F7001C3BDB /* App */, + 0296B3022F38F8F7001C3BDB /* UnitTests */, + 0296B30C2F38F8F7001C3BDB /* UITests */, 0296B2F12F38F8F7001C3BDB /* Products */, ); sourceTree = ""; @@ -105,14 +99,10 @@ ); buildRules = ( ); - dependencies = ( - ); fileSystemSynchronizedGroups = ( - 0296B2F22F38F8F7001C3BDB /* Todos */, + 0296B2F22F38F8F7001C3BDB /* App */, ); name = Todos; - packageProductDependencies = ( - ); productName = Todos; productReference = 0296B2F02F38F8F7001C3BDB /* Todos.app */; productType = "com.apple.product-type.application"; @@ -131,11 +121,9 @@ 0296B3012F38F8F7001C3BDB /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( - 0296B3022F38F8F7001C3BDB /* TodosTests */, + 0296B3022F38F8F7001C3BDB /* UnitTests */, ); name = TodosTests; - packageProductDependencies = ( - ); productName = TodosTests; productReference = 0296B2FF2F38F8F7001C3BDB /* TodosTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -154,11 +142,9 @@ 0296B30B2F38F8F7001C3BDB /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( - 0296B30C2F38F8F7001C3BDB /* TodosUITests */, + 0296B30C2F38F8F7001C3BDB /* UITests */, ); name = TodosUITests; - packageProductDependencies = ( - ); productName = TodosUITests; productReference = 0296B3092F38F8F7001C3BDB /* TodosUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; @@ -172,6 +158,7 @@ BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 2630; LastUpgradeCheck = 2630; + ORGANIZATIONNAME = "Röck+Cöde VoF"; TargetAttributes = { 0296B2EF2F38F8F7001C3BDB = { CreatedOnToolsVersion = 26.3; @@ -195,7 +182,7 @@ ); mainGroup = 0296B2E72F38F8F7001C3BDB; minimizedProjectReferenceProxies = 1; - preferredProjectObjectVersion = 77; + preferredProjectObjectVersion = 90; productRefGroup = 0296B2F12F38F8F7001C3BDB /* Products */; projectDirPath = ""; projectRoot = ""; @@ -210,48 +197,36 @@ /* Begin PBXResourcesBuildPhase section */ 0296B2EE2F38F8F7001C3BDB /* Resources */ = { isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; 0296B2FD2F38F8F7001C3BDB /* Resources */ = { isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; 0296B3072F38F8F7001C3BDB /* Resources */ = { isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 0296B2EC2F38F8F7001C3BDB /* Sources */ = { isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; 0296B2FB2F38F8F7001C3BDB /* Sources */ = { isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; 0296B3052F38F8F7001C3BDB /* Sources */ = { isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; files = ( ); - runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ @@ -269,7 +244,7 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 0296B3112F38F8F7001C3BDB /* Debug */ = { + 0296B3112F38F8F7001C3BDB /* Debug configuration for PBXProject "Todos" */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -331,7 +306,7 @@ }; name = Debug; }; - 0296B3122F38F8F7001C3BDB /* Release */ = { + 0296B3122F38F8F7001C3BDB /* Release configuration for PBXProject "Todos" */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -385,7 +360,7 @@ }; name = Release; }; - 0296B3142F38F8F7001C3BDB /* Debug */ = { + 0296B3142F38F8F7001C3BDB /* Debug configuration for PBXNativeTarget "Todos" */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -413,7 +388,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 26.2; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.app.Todos"; + PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app"; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; SDKROOT = auto; @@ -429,7 +404,7 @@ }; name = Debug; }; - 0296B3152F38F8F7001C3BDB /* Release */ = { + 0296B3152F38F8F7001C3BDB /* Release configuration for PBXNativeTarget "Todos" */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -457,7 +432,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 26.2; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.app.Todos"; + PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app"; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; SDKROOT = auto; @@ -473,7 +448,7 @@ }; name = Release; }; - 0296B3172F38F8F7001C3BDB /* Debug */ = { + 0296B3172F38F8F7001C3BDB /* Debug configuration for PBXNativeTarget "TodosTests" */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; @@ -484,7 +459,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 26.2; MACOSX_DEPLOYMENT_TARGET = 26.2; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.app.TodosTests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.unit-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -499,7 +474,7 @@ }; name = Debug; }; - 0296B3182F38F8F7001C3BDB /* Release */ = { + 0296B3182F38F8F7001C3BDB /* Release configuration for PBXNativeTarget "TodosTests" */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; @@ -510,7 +485,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 26.2; MACOSX_DEPLOYMENT_TARGET = 26.2; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.app.TodosTests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.unit-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -525,7 +500,7 @@ }; name = Release; }; - 0296B31A2F38F8F7001C3BDB /* Debug */ = { + 0296B31A2F38F8F7001C3BDB /* Debug configuration for PBXNativeTarget "TodosUITests" */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; @@ -535,7 +510,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 26.2; MACOSX_DEPLOYMENT_TARGET = 26.2; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.app.TodosUITests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.ui-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -550,7 +525,7 @@ }; name = Debug; }; - 0296B31B2F38F8F7001C3BDB /* Release */ = { + 0296B31B2F38F8F7001C3BDB /* Release configuration for PBXNativeTarget "TodosUITests" */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; @@ -560,7 +535,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 26.2; MACOSX_DEPLOYMENT_TARGET = 26.2; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.app.TodosUITests"; + PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.ui-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -581,37 +556,33 @@ 0296B2EB2F38F8F7001C3BDB /* Build configuration list for PBXProject "Todos" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0296B3112F38F8F7001C3BDB /* Debug */, - 0296B3122F38F8F7001C3BDB /* Release */, + 0296B3112F38F8F7001C3BDB /* Debug configuration for PBXProject "Todos" */, + 0296B3122F38F8F7001C3BDB /* Release configuration for PBXProject "Todos" */, ); - defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0296B3132F38F8F7001C3BDB /* Build configuration list for PBXNativeTarget "Todos" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0296B3142F38F8F7001C3BDB /* Debug */, - 0296B3152F38F8F7001C3BDB /* Release */, + 0296B3142F38F8F7001C3BDB /* Debug configuration for PBXNativeTarget "Todos" */, + 0296B3152F38F8F7001C3BDB /* Release configuration for PBXNativeTarget "Todos" */, ); - defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0296B3162F38F8F7001C3BDB /* Build configuration list for PBXNativeTarget "TodosTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0296B3172F38F8F7001C3BDB /* Debug */, - 0296B3182F38F8F7001C3BDB /* Release */, + 0296B3172F38F8F7001C3BDB /* Debug configuration for PBXNativeTarget "TodosTests" */, + 0296B3182F38F8F7001C3BDB /* Release configuration for PBXNativeTarget "TodosTests" */, ); - defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0296B3192F38F8F7001C3BDB /* Build configuration list for PBXNativeTarget "TodosUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0296B31A2F38F8F7001C3BDB /* Debug */, - 0296B31B2F38F8F7001C3BDB /* Release */, + 0296B31A2F38F8F7001C3BDB /* Debug configuration for PBXNativeTarget "TodosUITests" */, + 0296B31B2F38F8F7001C3BDB /* Release configuration for PBXNativeTarget "TodosUITests" */, ); - defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ diff --git a/TodosUITests/TodosUITests.swift b/UITests/TodosUITests.swift similarity index 100% rename from TodosUITests/TodosUITests.swift rename to UITests/TodosUITests.swift diff --git a/TodosUITests/TodosUITestsLaunchTests.swift b/UITests/TodosUITestsLaunchTests.swift similarity index 100% rename from TodosUITests/TodosUITestsLaunchTests.swift rename to UITests/TodosUITestsLaunchTests.swift diff --git a/TodosTests/TodosTests.swift b/UnitTests/TodosTests.swift similarity index 100% rename from TodosTests/TodosTests.swift rename to UnitTests/TodosTests.swift -- 2.54.0 From bff0b7c977b948990db1fa475f397cc051679991 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 8 Feb 2026 18:42:07 +0100 Subject: [PATCH 2/6] Updated the deployment targets for the app as well as unit and UI tests targets. --- Todos.xcodeproj/project.pbxproj | 38 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/Todos.xcodeproj/project.pbxproj b/Todos.xcodeproj/project.pbxproj index 71f1860..4ca1769 100644 --- a/Todos.xcodeproj/project.pbxproj +++ b/Todos.xcodeproj/project.pbxproj @@ -373,6 +373,7 @@ ENABLE_PREVIEWS = YES; ENABLE_USER_SELECTED_FILES = readonly; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; @@ -383,10 +384,10 @@ "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 26.2; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 26.2; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -400,7 +401,7 @@ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; - XROS_DEPLOYMENT_TARGET = 26.2; + XROS_DEPLOYMENT_TARGET = 26.0; }; name = Debug; }; @@ -417,6 +418,7 @@ ENABLE_PREVIEWS = YES; ENABLE_USER_SELECTED_FILES = readonly; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; @@ -427,10 +429,10 @@ "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 26.2; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 26.2; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -444,7 +446,7 @@ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; - XROS_DEPLOYMENT_TARGET = 26.2; + XROS_DEPLOYMENT_TARGET = 26.0; }; name = Release; }; @@ -456,8 +458,8 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 7FMNM89WKG; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.2; - MACOSX_DEPLOYMENT_TARGET = 26.2; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.unit-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -470,7 +472,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Todos.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Todos"; - XROS_DEPLOYMENT_TARGET = 26.2; + XROS_DEPLOYMENT_TARGET = 26.0; }; name = Debug; }; @@ -482,8 +484,8 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 7FMNM89WKG; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.2; - MACOSX_DEPLOYMENT_TARGET = 26.2; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.unit-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -496,7 +498,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Todos.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Todos"; - XROS_DEPLOYMENT_TARGET = 26.2; + XROS_DEPLOYMENT_TARGET = 26.0; }; name = Release; }; @@ -507,8 +509,8 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 7FMNM89WKG; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.2; - MACOSX_DEPLOYMENT_TARGET = 26.2; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.ui-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -521,7 +523,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_TARGET_NAME = Todos; - XROS_DEPLOYMENT_TARGET = 26.2; + XROS_DEPLOYMENT_TARGET = 26.0; }; name = Debug; }; @@ -532,8 +534,8 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 7FMNM89WKG; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 26.2; - MACOSX_DEPLOYMENT_TARGET = 26.2; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.rock-n-code.assignment.todos.app.ui-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -546,7 +548,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_TARGET_NAME = Todos; - XROS_DEPLOYMENT_TARGET = 26.2; + XROS_DEPLOYMENT_TARGET = 26.0; }; name = Release; }; -- 2.54.0 From 87660a84042f27d41aff5d16766ba4fe53336d1c Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 8 Feb 2026 18:46:02 +0100 Subject: [PATCH 3/6] Added the .gitignore file for the whole project. --- .gitignore | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bece1bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# Xcode +# General +.DS_Store +.AppleDouble +.LSOverride + +# Build generated +build/ +DerivedData/ +*.o +*.obj + +# Xcode +xcuserdata/ +*.xcuserstate +*.xcscmblueprint +*.xccheckout +*.xcdebugger +*.hmap +*.ipa +*.dSYM +*.dSYM.zip + +# Workspace settings (shared by team) - keep these under version control if desired +# Uncomment to keep WorkspaceSettings +# !xcshareddata/WorkspaceSettings.xcsettings + +# Xcode project user files +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +# Swift Package Manager +/.build/ +/.swiftpm/ +Package.resolved + +# Environment files +.env +.env.* + +# Archive / export +*.xcarchive + +# Ignore Swift PM artifact indexes +/.build/checkouts/ + +# macOS +.DS_Store \ No newline at end of file -- 2.54.0 From 8b6ec177afec0f68d7ebd3a7838766fbeb8f243c Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 8 Feb 2026 18:48:59 +0100 Subject: [PATCH 4/6] Created a README file for the project. --- README.md | 16 ++++++++++++++++ Todos.xcodeproj/project.pbxproj | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..95f56fe --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# TODOS + +A simple, small but complete todo app created for a technical interview with [Bol](https://www.bol.com), built using [SwiftUI](https://developer.apple.com/swiftui/). + +In a nutshell, this basic app should allow a user to either create, update, and/or delete tasks; as well as being able to mark tasks as completed. + +Given the requirements, the app should comply to the following criteria: + +* each task should have a title, optional description, due date, and a flag indicating if it’s completed. +* tasks should be grouped visually by their due date, such as Today, Upcoming, or Past. +* users should also be able to reorder tasks within a group using drag and drop functionality. +* data should be saved and loaded asynchronously, and the UI should remain responsive while these operations take place. +* should be possible to simulate delays with built-in tools if needed. + +Furthermore, the app is required to be built using SwiftUI with a clear structure that separates concerns. Any architectural style can be used, but the reasoning should be visible in how the code is organized. +It is expected that the app is modular and maintainable, so the source code must reflects this requirement. It is optional to include testable parts and anything extra that might improve the app. diff --git a/Todos.xcodeproj/project.pbxproj b/Todos.xcodeproj/project.pbxproj index 4ca1769..ba18a50 100644 --- a/Todos.xcodeproj/project.pbxproj +++ b/Todos.xcodeproj/project.pbxproj @@ -6,6 +6,10 @@ objectVersion = 90; objects = { +/* Begin PBXBuildFile section */ + 0296B3232F3903E6001C3BDB /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0296B3222F3903E6001C3BDB /* README.md */; }; +/* End PBXBuildFile section */ + /* Begin PBXContainerItemProxy section */ 0296B3002F38F8F7001C3BDB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -27,6 +31,7 @@ 0296B2F02F38F8F7001C3BDB /* Todos.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Todos.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0296B2FF2F38F8F7001C3BDB /* TodosTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TodosTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0296B3092F38F8F7001C3BDB /* TodosUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TodosUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 0296B3222F3903E6001C3BDB /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ @@ -69,6 +74,7 @@ 0296B2E72F38F8F7001C3BDB = { isa = PBXGroup; children = ( + 0296B3222F3903E6001C3BDB /* README.md */, 0296B2F22F38F8F7001C3BDB /* App */, 0296B3022F38F8F7001C3BDB /* UnitTests */, 0296B30C2F38F8F7001C3BDB /* UITests */, @@ -198,6 +204,7 @@ 0296B2EE2F38F8F7001C3BDB /* Resources */ = { isa = PBXResourcesBuildPhase; files = ( + 0296B3232F3903E6001C3BDB /* README.md in Resources */, ); }; 0296B2FD2F38F8F7001C3BDB /* Resources */ = { -- 2.54.0 From d97b49a1bde1b3d34cd3de66463876790dc89363 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 8 Feb 2026 20:57:36 +0100 Subject: [PATCH 5/6] Configured the Swift Format rules for the project. --- .gitignore | 3 +- .swift-format | 76 +++++++++++++++++++++++++++++++++ Todos.xcodeproj/project.pbxproj | 4 ++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 .swift-format diff --git a/.gitignore b/.gitignore index bece1bb..a3d98cb 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,5 @@ Package.resolved /.build/checkouts/ # macOS -.DS_Store \ No newline at end of file +.DS_Store + diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..1c16635 --- /dev/null +++ b/.swift-format @@ -0,0 +1,76 @@ +{ + "fileScopedDeclarationPrivacy": { + "accessLevel": "private" + }, + "indentBlankLines": false, + "indentConditionalCompilationBlocks": false, + "indentSwitchCaseLabels": true, + "indentation": { + "spaces": 4 + }, + "lineBreakAroundMultilineExpressionChainComponents": true, + "lineBreakBeforeControlFlowKeywords": true, + "lineBreakBeforeEachArgument": true, + "lineBreakBeforeEachGenericRequirement": false, + "lineBreakBetweenDeclarationAttributes": true, + "lineLength": 120, + "maximumBlankLines": 1, + "multilineTrailingCommaBehavior": "keptAsWritten", + "multiElementCollectionTrailingCommas": true, + "noAssignmentInExpressions" : { + "allowedFunctions" : [ + "XCTAssertNoThrow" + ] + }, + "orderedImports": { + "includeConditionalImports": true, + "shouldGroupImports": true + }, + "prioritizeKeepingFunctionOutputTogether": true, + "reflowMultilineStringLiterals": "always", + "respectsExistingLineBreaks": true, + "rules": { + "AllPublicDeclarationsHaveDocumentation": true, + "AlwaysUseLiteralForEmptyCollectionInit": true, + "AlwaysUseLowerCamelCase": true, + "AmbiguousTrailingClosureOverload": false, + "AvoidRetroactiveConformances": true, + "BeginDocumentationCommentWithOneLineSummary": true, + "DoNotUseSemicolons": true, + "DontRepeatTypeInStaticProperties": true, + "FullyIndirectEnum": true, + "IdentifiersMustBeASCII": true, + "NeverForceUnwrap": true, + "NeverUseForceTry": true, + "NeverUseImplicitlyUnwrappedOptionals": true, + "NoAccessLevelOnExtensionDeclarations": false, + "NoAssignmentInExpressions": true, + "NoBlockComments": true, + "NoCasesWithOnlyFallthrough": true, + "NoEmptyLinesOpeningClosingBraces": false, + "NoEmptyTrailingClosureParentheses": true, + "NoLabelsInCasePatterns": true, + "NoLeadingUnderscores": true, + "NoParensAroundConditions": true, + "NoPlaygroundLiterals": true, + "NoVoidReturnOnFunctionSignature": true, + "OneCasePerLine": true, + "OneVariableDeclarationPerLine": true, + "OnlyOneTrailingClosureArgument": true, + "OrderedImports" : true, + "ReturnVoidInsteadOfEmptyTuple": true, + "TypeNamesShouldBeCapitalized": true, + "UseEarlyExits": true, + "UseExplicitNilCheckInConditions": true, + "UseLetInEveryBoundCaseVariable": true, + "UseShorthandTypeNames": true, + "UseSynthesizedInitializer": true, + "UseTripleSlashForDocumentationComments": true, + "UseWhereClausesInForLoops": true, + "ValidateDocumentationComments": true + }, + "spacesAroundRangeFormationOperators": true, + "spacesBeforeEndOfLineComments" : 2, + "tabWidth": 4, + "version": 1 +} diff --git a/Todos.xcodeproj/project.pbxproj b/Todos.xcodeproj/project.pbxproj index ba18a50..da9cfef 100644 --- a/Todos.xcodeproj/project.pbxproj +++ b/Todos.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 0296B3232F3903E6001C3BDB /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0296B3222F3903E6001C3BDB /* README.md */; }; + 0296B3272F390E1A001C3BDB /* .swift-format in Resources */ = {isa = PBXBuildFile; fileRef = 0296B3262F390E1A001C3BDB /* .swift-format */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -32,6 +33,7 @@ 0296B2FF2F38F8F7001C3BDB /* TodosTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TodosTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0296B3092F38F8F7001C3BDB /* TodosUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TodosUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0296B3222F3903E6001C3BDB /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 0296B3262F390E1A001C3BDB /* .swift-format */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".swift-format"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ @@ -74,6 +76,7 @@ 0296B2E72F38F8F7001C3BDB = { isa = PBXGroup; children = ( + 0296B3262F390E1A001C3BDB /* .swift-format */, 0296B3222F3903E6001C3BDB /* README.md */, 0296B2F22F38F8F7001C3BDB /* App */, 0296B3022F38F8F7001C3BDB /* UnitTests */, @@ -205,6 +208,7 @@ isa = PBXResourcesBuildPhase; files = ( 0296B3232F3903E6001C3BDB /* README.md in Resources */, + 0296B3272F390E1A001C3BDB /* .swift-format in Resources */, ); }; 0296B2FD2F38F8F7001C3BDB /* Resources */ = { -- 2.54.0 From f587893ba67e7aa1d432aac2519621589797fb91 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 8 Feb 2026 21:10:52 +0100 Subject: [PATCH 6/6] Formatted the boilerplated code in the app as well as the unit and UI tests targets. --- App/Sources/App/TodosApp.swift | 7 ++++--- App/Sources/Models/Item.swift | 2 +- App/Sources/Views/ContentView.swift | 18 +++++++++++------- UITests/TodosUITestsLaunchTests.swift | 2 +- UnitTests/TodosTests.swift | 4 ++-- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/App/Sources/App/TodosApp.swift b/App/Sources/App/TodosApp.swift index c8ef9ce..ebd7187 100644 --- a/App/Sources/App/TodosApp.swift +++ b/App/Sources/App/TodosApp.swift @@ -1,17 +1,18 @@ -import SwiftUI import SwiftData +import SwiftUI @main struct TodosApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ - Item.self, + Item.self ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) - } catch { + } + catch { fatalError("Could not create ModelContainer: \(error)") } }() diff --git a/App/Sources/Models/Item.swift b/App/Sources/Models/Item.swift index dd0170c..a2f85bf 100644 --- a/App/Sources/Models/Item.swift +++ b/App/Sources/Models/Item.swift @@ -4,7 +4,7 @@ import SwiftData @Model final class Item { var timestamp: Date - + init(timestamp: Date) { self.timestamp = timestamp } diff --git a/App/Sources/Views/ContentView.swift b/App/Sources/Views/ContentView.swift index 69f91e5..e28a317 100644 --- a/App/Sources/Views/ContentView.swift +++ b/App/Sources/Views/ContentView.swift @@ -1,9 +1,13 @@ -import SwiftUI import SwiftData +import SwiftUI struct ContentView: View { - @Environment(\.modelContext) private var modelContext - @Query private var items: [Item] + + @Environment(\.modelContext) + private var modelContext + + @Query + private var items: [Item] var body: some View { NavigationSplitView { @@ -17,15 +21,15 @@ struct ContentView: View { } .onDelete(perform: deleteItems) } -#if os(macOS) + #if os(macOS) .navigationSplitViewColumnWidth(min: 180, ideal: 200) -#endif + #endif .toolbar { -#if os(iOS) + #if os(iOS) ToolbarItem(placement: .navigationBarTrailing) { EditButton() } -#endif + #endif ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") diff --git a/UITests/TodosUITestsLaunchTests.swift b/UITests/TodosUITestsLaunchTests.swift index cd2ccdc..b3a45ef 100644 --- a/UITests/TodosUITestsLaunchTests.swift +++ b/UITests/TodosUITestsLaunchTests.swift @@ -23,5 +23,5 @@ final class TodosUITestsLaunchTests: XCTestCase { attachment.lifetime = .keepAlways add(attachment) } -} +} diff --git a/UnitTests/TodosTests.swift b/UnitTests/TodosTests.swift index 89b14c6..7ac4a8a 100644 --- a/UnitTests/TodosTests.swift +++ b/UnitTests/TodosTests.swift @@ -2,8 +2,8 @@ import Testing struct TodosTests { - @Test func example() async throws { + @Test + func example() async throws { // Write your test here and use APIs like `#expect(...)` to check expected conditions. } - } -- 2.54.0