Use production CloudKit environment for Xcode builds

Development-signed builds now opt into the Production CloudKit
environment via com.apple.developer.icloud-container-environment,
driven by a CLOUDKIT_ENV build setting. A new Debug-CKDev configuration
and "Yattee (CloudKit Dev)" scheme switch to the Development
environment for schema work.

The DEV badge and banner in iCloud settings now reflect the actual
environment (YatteeCloudKitEnvironment Info.plist key) instead of
#if DEBUG, and the sync engine logs the environment at startup.
This commit is contained in:
Arkadiusz Fal
2026-10-23 21:47:34 +02:00
parent c60f483d3c
commit 2a49a5db68
11 changed files with 388 additions and 28 deletions

View File

@@ -384,7 +384,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ \"${CONFIGURATION}\" = \"Release-DeveloperID\" ] || [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n echo \"Skipping Sparkle strip (config=${CONFIGURATION})\"\n exit 0\nfi\nFW=\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework\"\nif [ -d \"$FW\" ]; then\n echo \"Stripping Sparkle.framework (config=${CONFIGURATION})\"\n chflags -R nouchg \"$FW\" 2>/dev/null || true\n chmod -R u+w \"$FW\" 2>/dev/null || true\n TMP=\"${FW}.stripping.$$\"\n if mv \"$FW\" \"$TMP\" 2>/dev/null; then\n TARGET=\"$TMP\"\n else\n TARGET=\"$FW\"\n fi\n for i in 1 2 3 4 5; do\n rm -rf \"$TARGET\" && break\n sleep 0.2\n done\n if [ -e \"$TARGET\" ]; then\n echo \"warning: failed to fully remove $TARGET\" >&2\n exit 1\n fi\nfi\n";
shellScript = "if [ \"${CONFIGURATION}\" = \"Release-DeveloperID\" ] || [ \"${CONFIGURATION}\" = \"Debug\" ] || [ \"${CONFIGURATION}\" = \"Debug-CKDev\" ]; then\n echo \"Skipping Sparkle strip (config=${CONFIGURATION})\"\n exit 0\nfi\nFW=\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework\"\nif [ -d \"$FW\" ]; then\n echo \"Stripping Sparkle.framework (config=${CONFIGURATION})\"\n chflags -R nouchg \"$FW\" 2>/dev/null || true\n chmod -R u+w \"$FW\" 2>/dev/null || true\n TMP=\"${FW}.stripping.$$\"\n if mv \"$FW\" \"$TMP\" 2>/dev/null; then\n TARGET=\"$TMP\"\n else\n TARGET=\"$FW\"\n fi\n for i in 1 2 3 4 5; do\n rm -rf \"$TARGET\" && break\n sleep 0.2\n done\n if [ -e \"$TARGET\" ]; then\n echo \"warning: failed to fully remove $TARGET\" >&2\n exit 1\n fi\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -445,6 +445,7 @@
372D1A302EDB163900F58F7A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLOUDKIT_ENV = Production;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
@@ -506,9 +507,75 @@
};
name = Debug;
};
37CCD0E00000000000000001 /* Debug-CKDev */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLOUDKIT_ENV = Development;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 78Z5H3M6RJ;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = "Debug-CKDev";
};
372D1A312EDB163900F58F7A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLOUDKIT_ENV = Production;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
@@ -647,6 +714,91 @@
};
name = Debug;
};
37CCD0E00000000000000002 /* Debug-CKDev */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = Yattee2;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
AUTOMATION_APPLE_EVENTS = NO;
CODE_SIGN_ENTITLEMENTS = Yattee/Yattee.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 275;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 78Z5H3M6RJ;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES;
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = YES;
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
ENABLE_RESOURCE_ACCESS_USB = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
ENABLE_USER_SELECTED_FILES = readwrite;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
"GLES_SILENCE_DEPRECATION=1",
"GL_SILENCE_DEPRECATION=1",
);
GENERATE_INFOPLIST_FILE = YES;
HEADER_SEARCH_PATHS = (
"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Libsmbclient.framework/Headers/samba-4.0",
"$(BUILT_PRODUCTS_DIR)/Libsmbclient.framework/Headers/samba-4.0",
);
INFOPLIST_FILE = Yattee/Info.plist;
"INFOPLIST_FILE[sdk=appletvos*]" = "Yattee/Info-tvOS.plist";
"INFOPLIST_FILE[sdk=appletvsimulator*]" = "Yattee/Info-tvOS.plist";
INFOPLIST_KEY_CFBundleDisplayName = Yattee;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.video";
INFOPLIST_KEY_NSHumanReadableCopyright = "© 2026 Arkadiusz Fal";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "Yattee uses local network to discover and control playback on other Yattee devices.";
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 2.0.0;
PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO;
RUNTIME_EXCEPTION_ALLOW_JIT = NO;
RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = YES;
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES;
SDKROOT = auto;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Yattee/Yattee-Bridging-Header.h";
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TVOS_DEPLOYMENT_TARGET = 18.0;
XROS_DEPLOYMENT_TARGET = 26.1;
};
name = "Debug-CKDev";
};
372D1A342EDB163900F58F7A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -738,6 +890,7 @@
376D70452F996E0700255B09 /* Release-DeveloperID */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLOUDKIT_ENV = Production;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
@@ -1003,6 +1156,37 @@
};
name = Debug;
};
37CCD0E00000000000000003 /* Debug-CKDev */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = YatteeShareExtension/YatteeShareExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 275;
DEVELOPMENT_TEAM = 78Z5H3M6RJ;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = YatteeShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Yattee Share Extension";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.0.0;
PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = "Debug-CKDev";
};
37BA19B82EE4EB7F001D7B0F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1069,6 +1253,40 @@
};
name = Debug;
};
37CCD0E00000000000000004 /* Debug-CKDev */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = YatteeTopShelf/YatteeTopShelf.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 275;
DEVELOPMENT_TEAM = 78Z5H3M6RJ;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = YatteeTopShelf/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Yattee Top Shelf";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_ENTRY_POINT = _NSExtensionMain;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.0.0;
PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app.TopShelf;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator";
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 18.0;
};
name = "Debug-CKDev";
};
37C0AAAA00000000AAAA000B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1133,6 +1351,35 @@
};
name = Debug;
};
37CCD0E00000000000000005 /* Debug-CKDev */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 275;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 78Z5H3M6RJ;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = stream.yattee.app.YatteeTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
STRING_CATALOG_GENERATE_SYMBOLS = NO;
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,3";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Yattee.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Yattee";
TVOS_DEPLOYMENT_TARGET = 18.0;
XROS_DEPLOYMENT_TARGET = 26.1;
};
name = "Debug-CKDev";
};
37D0B29C2EDB23BD00B9C4ED /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1169,6 +1416,7 @@
isa = XCConfigurationList;
buildConfigurations = (
372D1A302EDB163900F58F7A /* Debug */,
37CCD0E00000000000000001 /* Debug-CKDev */,
372D1A312EDB163900F58F7A /* Release */,
376D70452F996E0700255B09 /* Release-DeveloperID */,
);
@@ -1179,6 +1427,7 @@
isa = XCConfigurationList;
buildConfigurations = (
372D1A332EDB163900F58F7A /* Debug */,
37CCD0E00000000000000002 /* Debug-CKDev */,
372D1A342EDB163900F58F7A /* Release */,
376D70462F996E0700255B09 /* Release-DeveloperID */,
);
@@ -1189,6 +1438,7 @@
isa = XCConfigurationList;
buildConfigurations = (
37BA19B72EE4EB7F001D7B0F /* Debug */,
37CCD0E00000000000000003 /* Debug-CKDev */,
37BA19B82EE4EB7F001D7B0F /* Release */,
376D70482F996E0700255B09 /* Release-DeveloperID */,
);
@@ -1199,6 +1449,7 @@
isa = XCConfigurationList;
buildConfigurations = (
37C0AAAA00000000AAAA000A /* Debug */,
37CCD0E00000000000000004 /* Debug-CKDev */,
37C0AAAA00000000AAAA000B /* Release */,
376D70492F996E0700255B09 /* Release-DeveloperID */,
);
@@ -1209,6 +1460,7 @@
isa = XCConfigurationList;
buildConfigurations = (
37D0B29B2EDB23BD00B9C4ED /* Debug */,
37CCD0E00000000000000005 /* Debug-CKDev */,
37D0B29C2EDB23BD00B9C4ED /* Release */,
376D70472F996E0700255B09 /* Release-DeveloperID */,
);

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "2630"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "372D1A262EDB163800F58F7A"
BuildableName = "Yattee.app"
BlueprintName = "Yattee"
ReferencedContainer = "container:Yattee.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug-CKDev"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "37D0B2932EDB23BD00B9C4ED"
BuildableName = "YatteeTests.xctest"
BlueprintName = "YatteeTests"
ReferencedContainer = "container:Yattee.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug-CKDev"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "372D1A262EDB163800F58F7A"
BuildableName = "Yattee.app"
BlueprintName = "Yattee"
ReferencedContainer = "container:Yattee.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "372D1A262EDB163800F58F7A"
BuildableName = "Yattee.app"
BlueprintName = "Yattee"
ReferencedContainer = "container:Yattee.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug-CKDev">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -12,6 +12,17 @@ enum AppIdentifiers {
"iCloud.\(bundleIdentifier)"
}
/// CloudKit environment this build is signed for ("Development" or "Production"),
/// from the `CLOUDKIT_ENV` build setting. Debug builds use Production unless
/// built with the Debug-CKDev configuration ("Yattee (CloudKit Dev)" scheme).
static var iCloudEnvironment: String {
Bundle.main.object(forInfoDictionaryKey: "YatteeCloudKitEnvironment") as? String ?? "Production"
}
static var isCloudKitDevelopmentEnvironment: Bool {
iCloudEnvironment == "Development"
}
// MARK: - Background Tasks
static var backgroundFeedRefresh: String {

View File

@@ -37,6 +37,8 @@
<array>
<string>stream.yattee.app.activity</string>
</array>
<key>YatteeCloudKitEnvironment</key>
<string>$(CLOUDKIT_ENV)</string>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>

View File

@@ -46,6 +46,8 @@
<array>
<string>stream.yattee.app.activity</string>
</array>
<key>YatteeCloudKitEnvironment</key>
<string>$(CLOUDKIT_ENV)</string>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>

View File

@@ -13673,7 +13673,6 @@
}
},
"settings.icloud.dev.badge" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -13684,7 +13683,6 @@
}
},
"settings.icloud.dev.footer" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -13695,7 +13693,6 @@
}
},
"settings.icloud.dev.title" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {

View File

@@ -311,6 +311,7 @@ final class CloudKitSyncEngine: @unchecked Sendable {
self.container = container
self.database = database
self.zoneManager = CloudKitZoneManager(database: database)
LoggingService.shared.logCloudKit("CloudKit environment: \(AppIdentifiers.iCloudEnvironment)")
} else {
LoggingService.shared.logCloudKit("iCloud container entitlement missing (re-signed build) - CloudKit sync unavailable")
self.container = nil

View File

@@ -167,15 +167,15 @@ struct SettingsView: View {
} label: {
HStack {
Label(String(localized: "settings.icloud.title"), systemImage: "icloud")
#if DEBUG
Spacer()
Text(String(localized: "settings.icloud.dev.badge"))
.font(.caption2.bold())
.foregroundStyle(.white)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(.orange, in: Capsule())
#endif
if AppIdentifiers.isCloudKitDevelopmentEnvironment {
Spacer()
Text(String(localized: "settings.icloud.dev.badge"))
.font(.caption2.bold())
.foregroundStyle(.white)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(.orange, in: Capsule())
}
}
}
@@ -287,15 +287,15 @@ struct SettingsView: View {
} label: {
HStack {
Label(String(localized: "settings.icloud.title"), systemImage: "icloud")
#if DEBUG
Spacer()
Text(String(localized: "settings.icloud.dev.badge"))
.font(.caption2.bold())
.foregroundStyle(.white)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(.orange, in: Capsule())
#endif
if AppIdentifiers.isCloudKitDevelopmentEnvironment {
Spacer()
Text(String(localized: "settings.icloud.dev.badge"))
.font(.caption2.bold())
.foregroundStyle(.white)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(.orange, in: Capsule())
}
}
}

View File

@@ -50,13 +50,13 @@ struct iCloudSettingsView: View {
var body: some View {
SettingsFormContainer {
#if DEBUG
SettingsFormSection(footer: "settings.icloud.dev.footer") {
Label(String(localized: "settings.icloud.dev.title"), systemImage: "hammer.fill")
.foregroundStyle(.orange)
.font(.subheadline)
if AppIdentifiers.isCloudKitDevelopmentEnvironment {
SettingsFormSection(footer: "settings.icloud.dev.footer") {
Label(String(localized: "settings.icloud.dev.title"), systemImage: "hammer.fill")
.foregroundStyle(.orange)
.font(.subheadline)
}
}
#endif
if cloudKitSync?.isCloudKitAvailable == false {
SettingsFormSection(footer: "settings.icloud.unavailable.footer") {

View File

@@ -4,6 +4,8 @@
<dict>
<key>com.apple.developer.aps-environment</key>
<string>production</string>
<key>com.apple.developer.icloud-container-environment</key>
<string>$(CLOUDKIT_ENV)</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.$(CFBundleIdentifier)</string>

View File

@@ -4,6 +4,8 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.icloud-container-environment</key>
<string>$(CLOUDKIT_ENV)</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.$(CFBundleIdentifier)</string>