@craft-native/ios 0.0.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,247 @@
1
+ import WidgetKit
2
+ import SwiftUI
3
+
4
+ // MARK: - Widget Entry
5
+ struct CraftWidgetEntry: TimelineEntry {
6
+ let date: Date
7
+ let title: String
8
+ let subtitle: String
9
+ let value: String
10
+ let iconName: String?
11
+ let configuration: ConfigurationIntent?
12
+ }
13
+
14
+ // MARK: - Widget Provider
15
+ struct CraftWidgetProvider: IntentTimelineProvider {
16
+ typealias Entry = CraftWidgetEntry
17
+ typealias Intent = ConfigurationIntent
18
+
19
+ // Shared UserDefaults for app-to-widget communication
20
+ private let sharedDefaults = UserDefaults(suiteName: "group.{{BUNDLE_ID}}.widget")
21
+
22
+ func placeholder(in context: Context) -> CraftWidgetEntry {
23
+ CraftWidgetEntry(
24
+ date: Date(),
25
+ title: "Craft Widget",
26
+ subtitle: "Loading...",
27
+ value: "",
28
+ iconName: nil,
29
+ configuration: nil
30
+ )
31
+ }
32
+
33
+ func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (CraftWidgetEntry) -> Void) {
34
+ let entry = loadWidgetData(configuration: configuration)
35
+ completion(entry)
36
+ }
37
+
38
+ func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<CraftWidgetEntry>) -> Void) {
39
+ let entry = loadWidgetData(configuration: configuration)
40
+
41
+ // Refresh every 15 minutes
42
+ let nextUpdate = Calendar.current.date(byAdding: .minute, value: 15, to: Date())!
43
+ let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
44
+ completion(timeline)
45
+ }
46
+
47
+ private func loadWidgetData(configuration: ConfigurationIntent?) -> CraftWidgetEntry {
48
+ let title = sharedDefaults?.string(forKey: "widget_title") ?? "Craft Widget"
49
+ let subtitle = sharedDefaults?.string(forKey: "widget_subtitle") ?? ""
50
+ let value = sharedDefaults?.string(forKey: "widget_value") ?? ""
51
+ let iconName = sharedDefaults?.string(forKey: "widget_icon")
52
+
53
+ return CraftWidgetEntry(
54
+ date: Date(),
55
+ title: title,
56
+ subtitle: subtitle,
57
+ value: value,
58
+ iconName: iconName,
59
+ configuration: configuration
60
+ )
61
+ }
62
+ }
63
+
64
+ // MARK: - Small Widget View
65
+ struct CraftWidgetSmallView: View {
66
+ var entry: CraftWidgetEntry
67
+
68
+ var body: some View {
69
+ VStack(alignment: .leading, spacing: 4) {
70
+ if let iconName = entry.iconName {
71
+ Image(systemName: iconName)
72
+ .font(.title2)
73
+ .foregroundColor(.accentColor)
74
+ }
75
+
76
+ Text(entry.title)
77
+ .font(.headline)
78
+ .lineLimit(2)
79
+
80
+ if !entry.subtitle.isEmpty {
81
+ Text(entry.subtitle)
82
+ .font(.caption)
83
+ .foregroundColor(.secondary)
84
+ .lineLimit(1)
85
+ }
86
+
87
+ Spacer()
88
+
89
+ if !entry.value.isEmpty {
90
+ Text(entry.value)
91
+ .font(.title)
92
+ .fontWeight(.bold)
93
+ .foregroundColor(.accentColor)
94
+ }
95
+ }
96
+ .padding()
97
+ .widgetBackground(Color(.systemBackground))
98
+ }
99
+ }
100
+
101
+ // MARK: - Medium Widget View
102
+ struct CraftWidgetMediumView: View {
103
+ var entry: CraftWidgetEntry
104
+
105
+ var body: some View {
106
+ HStack {
107
+ VStack(alignment: .leading, spacing: 4) {
108
+ if let iconName = entry.iconName {
109
+ Image(systemName: iconName)
110
+ .font(.title)
111
+ .foregroundColor(.accentColor)
112
+ }
113
+
114
+ Text(entry.title)
115
+ .font(.headline)
116
+
117
+ if !entry.subtitle.isEmpty {
118
+ Text(entry.subtitle)
119
+ .font(.subheadline)
120
+ .foregroundColor(.secondary)
121
+ }
122
+ }
123
+
124
+ Spacer()
125
+
126
+ if !entry.value.isEmpty {
127
+ Text(entry.value)
128
+ .font(.largeTitle)
129
+ .fontWeight(.bold)
130
+ .foregroundColor(.accentColor)
131
+ }
132
+ }
133
+ .padding()
134
+ .widgetBackground(Color(.systemBackground))
135
+ }
136
+ }
137
+
138
+ // MARK: - Large Widget View
139
+ struct CraftWidgetLargeView: View {
140
+ var entry: CraftWidgetEntry
141
+
142
+ var body: some View {
143
+ VStack(alignment: .leading, spacing: 8) {
144
+ HStack {
145
+ if let iconName = entry.iconName {
146
+ Image(systemName: iconName)
147
+ .font(.title)
148
+ .foregroundColor(.accentColor)
149
+ }
150
+
151
+ VStack(alignment: .leading) {
152
+ Text(entry.title)
153
+ .font(.headline)
154
+
155
+ if !entry.subtitle.isEmpty {
156
+ Text(entry.subtitle)
157
+ .font(.subheadline)
158
+ .foregroundColor(.secondary)
159
+ }
160
+ }
161
+
162
+ Spacer()
163
+ }
164
+
165
+ Divider()
166
+
167
+ if !entry.value.isEmpty {
168
+ Text(entry.value)
169
+ .font(.system(size: 48, weight: .bold))
170
+ .foregroundColor(.accentColor)
171
+ }
172
+
173
+ Spacer()
174
+
175
+ Text("Updated: \(entry.date, style: .time)")
176
+ .font(.caption2)
177
+ .foregroundColor(.secondary)
178
+ }
179
+ .padding()
180
+ .widgetBackground(Color(.systemBackground))
181
+ }
182
+ }
183
+
184
+ // MARK: - Widget Entry View
185
+ struct CraftWidgetEntryView: View {
186
+ var entry: CraftWidgetEntry
187
+ @Environment(\.widgetFamily) var family
188
+
189
+ var body: some View {
190
+ switch family {
191
+ case .systemSmall:
192
+ CraftWidgetSmallView(entry: entry)
193
+ case .systemMedium:
194
+ CraftWidgetMediumView(entry: entry)
195
+ case .systemLarge:
196
+ CraftWidgetLargeView(entry: entry)
197
+ default:
198
+ CraftWidgetSmallView(entry: entry)
199
+ }
200
+ }
201
+ }
202
+
203
+ // MARK: - Widget Configuration
204
+ @main
205
+ struct CraftWidget: Widget {
206
+ let kind: String = "CraftWidget"
207
+
208
+ var body: some WidgetConfiguration {
209
+ IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: CraftWidgetProvider()) { entry in
210
+ CraftWidgetEntryView(entry: entry)
211
+ }
212
+ .configurationDisplayName("{{APP_NAME}} Widget")
213
+ .description("Display information from {{APP_NAME}}")
214
+ .supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
215
+ }
216
+ }
217
+
218
+ // MARK: - Widget Background Extension
219
+ extension View {
220
+ func widgetBackground(_ color: Color) -> some View {
221
+ if #available(iOS 17.0, *) {
222
+ return containerBackground(color, for: .widget)
223
+ } else {
224
+ return background(color)
225
+ }
226
+ }
227
+ }
228
+
229
+ // MARK: - Configuration Intent (placeholder)
230
+ class ConfigurationIntent: INIntent {
231
+ // Add configuration properties here
232
+ }
233
+
234
+ // MARK: - Preview
235
+ struct CraftWidget_Previews: PreviewProvider {
236
+ static var previews: some View {
237
+ CraftWidgetEntryView(entry: CraftWidgetEntry(
238
+ date: Date(),
239
+ title: "My Widget",
240
+ subtitle: "Subtitle text",
241
+ value: "42",
242
+ iconName: "star.fill",
243
+ configuration: nil
244
+ ))
245
+ .previewContext(WidgetPreviewContext(family: .systemSmall))
246
+ }
247
+ }
@@ -0,0 +1,66 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>en</string>
7
+ <key>CFBundleDisplayName</key>
8
+ <string>{{APP_NAME}}</string>
9
+ <key>CFBundleExecutable</key>
10
+ <string>$(EXECUTABLE_NAME)</string>
11
+ <key>CFBundleIdentifier</key>
12
+ <string>{{BUNDLE_ID}}</string>
13
+ <key>CFBundleInfoDictionaryVersion</key>
14
+ <string>6.0</string>
15
+ <key>CFBundleName</key>
16
+ <string>{{APP_NAME}}</string>
17
+ <key>CFBundlePackageType</key>
18
+ <string>APPL</string>
19
+ <key>CFBundleShortVersionString</key>
20
+ <string>{{VERSION}}</string>
21
+ <key>CFBundleVersion</key>
22
+ <string>{{BUILD_NUMBER}}</string>
23
+ <key>LSRequiresIPhoneOS</key>
24
+ <true/>
25
+ <key>UILaunchScreen</key>
26
+ <dict>
27
+ <key>UIColorName</key>
28
+ <string>LaunchBackground</string>
29
+ </dict>
30
+ <key>UIRequiredDeviceCapabilities</key>
31
+ <array>
32
+ <string>arm64</string>
33
+ </array>
34
+ <key>UISupportedInterfaceOrientations</key>
35
+ <array>
36
+ {{ORIENTATIONS}}
37
+ </array>
38
+ <key>UIUserInterfaceStyle</key>
39
+ <string>{{UI_STYLE}}</string>
40
+ <key>UIStatusBarStyle</key>
41
+ <string>UIStatusBarStyleLightContent</string>
42
+ <key>UIViewControllerBasedStatusBarAppearance</key>
43
+ <false/>
44
+ {{USAGE_DESCRIPTIONS}}
45
+ {{URL_TYPES}}
46
+ {{BACKGROUND_MODES}}
47
+ {{LIVE_ACTIVITY_SUPPORT}}
48
+ <key>NSAppTransportSecurity</key>
49
+ <dict>
50
+ <key>NSAllowsLocalNetworking</key>
51
+ <true/>
52
+ <key>NSAllowsArbitraryLoads</key>
53
+ <false/>
54
+ <key>NSExceptionDomains</key>
55
+ <dict>
56
+ <key>localhost</key>
57
+ <dict>
58
+ <key>NSExceptionAllowsInsecureHTTPLoads</key>
59
+ <true/>
60
+ <key>NSIncludesSubdomains</key>
61
+ <true/>
62
+ </dict>
63
+ </dict>
64
+ </dict>
65
+ </dict>
66
+ </plist>
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleDisplayName</key>
8
+ <string>{{APP_NAME}}</string>
9
+ <key>CFBundleExecutable</key>
10
+ <string>$(EXECUTABLE_NAME)</string>
11
+ <key>CFBundleIdentifier</key>
12
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+ <key>CFBundleInfoDictionaryVersion</key>
14
+ <string>6.0</string>
15
+ <key>CFBundleName</key>
16
+ <string>$(PRODUCT_NAME)</string>
17
+ <key>CFBundlePackageType</key>
18
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
19
+ <key>CFBundleShortVersionString</key>
20
+ <string>$(MARKETING_VERSION)</string>
21
+ <key>CFBundleVersion</key>
22
+ <string>$(CURRENT_PROJECT_VERSION)</string>
23
+ <key>WKCompanionAppBundleIdentifier</key>
24
+ <string>{{BUNDLE_ID}}</string>
25
+ </dict>
26
+ </plist>
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleDisplayName</key>
8
+ <string>Live Activity</string>
9
+ <key>CFBundleExecutable</key>
10
+ <string>$(EXECUTABLE_NAME)</string>
11
+ <key>CFBundleIdentifier</key>
12
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+ <key>CFBundleInfoDictionaryVersion</key>
14
+ <string>6.0</string>
15
+ <key>CFBundleName</key>
16
+ <string>$(PRODUCT_NAME)</string>
17
+ <key>CFBundlePackageType</key>
18
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
19
+ <key>CFBundleShortVersionString</key>
20
+ <string>$(MARKETING_VERSION)</string>
21
+ <key>CFBundleVersion</key>
22
+ <string>$(CURRENT_PROJECT_VERSION)</string>
23
+ <key>NSExtension</key>
24
+ <dict>
25
+ <key>NSExtensionPointIdentifier</key>
26
+ <string>com.apple.widgetkit-extension</string>
27
+ </dict>
28
+ <key>NSSupportsLiveActivities</key>
29
+ <true/>
30
+ </dict>
31
+ </plist>
@@ -0,0 +1,45 @@
1
+ # Fastlane Appfile
2
+ # Stores App Store Connect and Apple Developer account information
3
+
4
+ # App Store Connect API Key (recommended for CI)
5
+ # app_store_connect_api_key(
6
+ # key_id: "YOUR_KEY_ID",
7
+ # issuer_id: "YOUR_ISSUER_ID",
8
+ # key_filepath: "./AuthKey_YOUR_KEY_ID.p8",
9
+ # in_house: false # Set to true for Enterprise accounts
10
+ # )
11
+
12
+ # Or use username/password authentication
13
+ # apple_id("your@email.com")
14
+
15
+ # Your app's bundle identifier
16
+ # app_identifier("com.yourcompany.craftapp")
17
+
18
+ # Your Apple Developer Team ID
19
+ # team_id("XXXXXXXXXX")
20
+
21
+ # App Store Connect Team ID (if different from Developer Portal)
22
+ # itc_team_id("XXXXXXXXXX")
23
+
24
+ # ==================== Example Configuration ====================
25
+ # Uncomment and modify:
26
+
27
+ # app_identifier("com.yourcompany.craftapp")
28
+ # apple_id("developer@yourcompany.com")
29
+ # team_id("ABCD1234XY")
30
+ # itc_team_id("ABCD1234XY")
31
+
32
+ # ==================== For CI/CD ====================
33
+ # Use App Store Connect API Key instead of username/password
34
+ # 1. Go to App Store Connect > Users and Access > Keys
35
+ # 2. Create a new API Key
36
+ # 3. Download the .p8 file
37
+ # 4. Store key_id, issuer_id, and key content as secrets
38
+ #
39
+ # In your Fastfile:
40
+ # api_key = app_store_connect_api_key(
41
+ # key_id: ENV["ASC_KEY_ID"],
42
+ # issuer_id: ENV["ASC_ISSUER_ID"],
43
+ # key_content: ENV["ASC_KEY_CONTENT"],
44
+ # is_key_content_base64: true
45
+ # )
@@ -0,0 +1,189 @@
1
+ # Craft iOS Fastlane Configuration
2
+ # Copy this directory to your ios/ folder
3
+ # Run: cd ios && bundle install && bundle exec fastlane <lane>
4
+
5
+ default_platform(:ios)
6
+
7
+ platform :ios do
8
+ # ==================== Setup ====================
9
+
10
+ desc "Setup code signing with match"
11
+ lane :setup_signing do
12
+ match(type: "development")
13
+ match(type: "appstore")
14
+ end
15
+
16
+ desc "Register new device for development"
17
+ lane :add_device do |options|
18
+ device_name = options[:name] || prompt(text: "Device name: ")
19
+ device_udid = options[:udid] || prompt(text: "Device UDID: ")
20
+
21
+ register_devices(
22
+ devices: { device_name => device_udid }
23
+ )
24
+
25
+ match(type: "development", force_for_new_devices: true)
26
+ end
27
+
28
+ # ==================== Build ====================
29
+
30
+ desc "Build for development"
31
+ lane :build_debug do
32
+ gym(
33
+ scheme: "CraftApp",
34
+ configuration: "Debug",
35
+ export_method: "development",
36
+ output_directory: "./build",
37
+ output_name: "CraftApp-Debug.ipa"
38
+ )
39
+ end
40
+
41
+ desc "Build for App Store"
42
+ lane :build_release do
43
+ # Ensure certificates are installed
44
+ match(type: "appstore", readonly: true)
45
+
46
+ # Increment build number
47
+ increment_build_number(xcodeproj: "CraftApp.xcodeproj")
48
+
49
+ # Build
50
+ gym(
51
+ scheme: "CraftApp",
52
+ configuration: "Release",
53
+ export_method: "app-store",
54
+ output_directory: "./build",
55
+ output_name: "CraftApp-Release.ipa",
56
+ include_bitcode: false
57
+ )
58
+ end
59
+
60
+ desc "Build for Ad-Hoc distribution"
61
+ lane :build_adhoc do
62
+ match(type: "adhoc", readonly: true)
63
+
64
+ increment_build_number(xcodeproj: "CraftApp.xcodeproj")
65
+
66
+ gym(
67
+ scheme: "CraftApp",
68
+ configuration: "Release",
69
+ export_method: "ad-hoc",
70
+ output_directory: "./build",
71
+ output_name: "CraftApp-AdHoc.ipa"
72
+ )
73
+ end
74
+
75
+ # ==================== Deploy ====================
76
+
77
+ desc "Upload to TestFlight"
78
+ lane :beta do
79
+ build_release
80
+
81
+ upload_to_testflight(
82
+ skip_waiting_for_build_processing: true,
83
+ distribute_external: false
84
+ )
85
+
86
+ # Notify Slack (optional)
87
+ # slack(
88
+ # message: "New TestFlight build uploaded! 🚀",
89
+ # channel: "#mobile-releases"
90
+ # )
91
+ end
92
+
93
+ desc "Upload to App Store"
94
+ lane :release do
95
+ build_release
96
+
97
+ upload_to_app_store(
98
+ skip_metadata: false,
99
+ skip_screenshots: true,
100
+ submit_for_review: false,
101
+ automatic_release: false,
102
+ precheck_include_in_app_purchases: false
103
+ )
104
+ end
105
+
106
+ # ==================== Testing ====================
107
+
108
+ desc "Run tests"
109
+ lane :test do
110
+ run_tests(
111
+ scheme: "CraftApp",
112
+ device: "iPhone 15",
113
+ code_coverage: true
114
+ )
115
+ end
116
+
117
+ desc "Run tests and report coverage"
118
+ lane :test_coverage do
119
+ run_tests(
120
+ scheme: "CraftApp",
121
+ device: "iPhone 15",
122
+ code_coverage: true,
123
+ output_directory: "./build/test-results"
124
+ )
125
+
126
+ # Generate coverage report (requires xcov)
127
+ # xcov(
128
+ # scheme: "CraftApp",
129
+ # output_directory: "./build/coverage"
130
+ # )
131
+ end
132
+
133
+ # ==================== Version Management ====================
134
+
135
+ desc "Bump version number"
136
+ lane :bump_version do |options|
137
+ bump_type = options[:type] || "patch" # major, minor, patch
138
+ increment_version_number(bump_type: bump_type)
139
+ version = get_version_number
140
+ UI.message("Version bumped to #{version}")
141
+ end
142
+
143
+ desc "Set version number"
144
+ lane :set_version do |options|
145
+ version = options[:version] || prompt(text: "Version number: ")
146
+ increment_version_number(version_number: version)
147
+ UI.message("Version set to #{version}")
148
+ end
149
+
150
+ # ==================== Utilities ====================
151
+
152
+ desc "Clean build artifacts"
153
+ lane :clean do
154
+ clear_derived_data
155
+ sh("rm -rf ../build")
156
+ UI.success("Build artifacts cleaned!")
157
+ end
158
+
159
+ desc "Sync certificates"
160
+ lane :sync_certs do
161
+ match(type: "development", readonly: true)
162
+ match(type: "appstore", readonly: true)
163
+ match(type: "adhoc", readonly: true)
164
+ end
165
+
166
+ # ==================== CI/CD ====================
167
+
168
+ desc "CI build and test"
169
+ lane :ci do
170
+ test
171
+ build_release
172
+ end
173
+
174
+ desc "CI deploy to TestFlight"
175
+ lane :ci_beta do
176
+ setup_ci
177
+
178
+ # Install certificates from match
179
+ match(
180
+ type: "appstore",
181
+ readonly: true,
182
+ keychain_name: "fastlane_tmp_keychain",
183
+ keychain_password: ""
184
+ )
185
+
186
+ build_release
187
+ upload_to_testflight(skip_waiting_for_build_processing: true)
188
+ end
189
+ end
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "fastlane", "~> 2.217"
4
+
5
+ # Plugins (optional)
6
+ plugins_path = File.join(File.dirname(__FILE__), 'Pluginfile')
7
+ eval_gemfile(plugins_path) if File.exist?(plugins_path)
@@ -0,0 +1,58 @@
1
+ # Fastlane Match Configuration
2
+ # Match manages iOS code signing certificates and provisioning profiles
3
+ # Certificates are stored in a private Git repository
4
+
5
+ # Git repository for storing certificates
6
+ # git_url("git@github.com:your-org/certificates.git")
7
+
8
+ # App identifier (bundle ID)
9
+ # app_identifier(["com.yourcompany.craftapp"])
10
+
11
+ # Your Apple Developer account
12
+ # username("your@email.com")
13
+
14
+ # Team ID (find in Developer Portal)
15
+ # team_id("XXXXXXXXXX")
16
+
17
+ # Storage mode: git, google_cloud, or s3
18
+ # storage_mode("git")
19
+
20
+ # Keychain for CI
21
+ # keychain_name(ENV["MATCH_KEYCHAIN_NAME"] || "login.keychain-db")
22
+
23
+ # ==================== Example Configuration ====================
24
+ # Uncomment and modify the following for your project:
25
+
26
+ # git_url("git@github.com:your-org/ios-certificates.git")
27
+ #
28
+ # app_identifier(["com.yourcompany.craftapp"])
29
+ # username("developer@yourcompany.com")
30
+ # team_id("ABCD1234XY")
31
+ #
32
+ # storage_mode("git")
33
+ #
34
+ # # For CI environments
35
+ # readonly(is_ci)
36
+ #
37
+ # # Types of profiles to manage
38
+ # type("development") # or "appstore", "adhoc", "enterprise"
39
+
40
+ # ==================== Usage ====================
41
+ # Initialize match (first time):
42
+ # fastlane match init
43
+ #
44
+ # Generate development certificates:
45
+ # fastlane match development
46
+ #
47
+ # Generate App Store certificates:
48
+ # fastlane match appstore
49
+ #
50
+ # Generate Ad-Hoc certificates:
51
+ # fastlane match adhoc
52
+ #
53
+ # Sync certificates (readonly):
54
+ # fastlane match development --readonly
55
+ #
56
+ # Force regenerate all certificates:
57
+ # fastlane match nuke development
58
+ # fastlane match nuke distribution