Skip to content

Commit ebc821f

Browse files
authored
Merge pull request #592 from tidepool-org/cameron/LOOP-4652-replace-anyview
[LOOP-4652] Replace AnyView
2 parents 140c2db + 3a8d2c9 commit ebc821f

File tree

5 files changed

+69
-43
lines changed

5 files changed

+69
-43
lines changed

Loop/View Controllers/StatusTableViewController.swift

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,22 +1385,46 @@ final class StatusTableViewController: LoopChartsTableViewController {
13851385
@IBAction func presentBolusScreen() {
13861386
presentBolusEntryView()
13871387
}
1388-
1389-
func presentBolusEntryView(enableManualGlucoseEntry: Bool = false) {
1390-
let hostingController: DismissibleHostingController
1388+
1389+
@ViewBuilder
1390+
func bolusEntryView(enableManualGlucoseEntry: Bool = false) -> some View {
13911391
if FeatureFlags.simpleBolusCalculatorEnabled && !automaticDosingStatus.automaticDosingEnabled {
1392-
let viewModel = SimpleBolusViewModel(delegate: deviceManager, displayMealEntry: false)
1393-
let bolusEntryView = SimpleBolusView(viewModel: viewModel).environmentObject(deviceManager.displayGlucosePreference)
1394-
hostingController = DismissibleHostingController(rootView: bolusEntryView, isModalInPresentation: false)
1392+
SimpleBolusView(
1393+
viewModel: SimpleBolusViewModel(
1394+
delegate: deviceManager,
1395+
displayMealEntry: false
1396+
)
1397+
)
1398+
.environmentObject(deviceManager.displayGlucosePreference)
13951399
} else {
1396-
let viewModel = BolusEntryViewModel(delegate: deviceManager, screenWidth: UIScreen.main.bounds.width, isManualGlucoseEntryEnabled: enableManualGlucoseEntry)
1397-
Task { @MainActor in
1398-
await viewModel.generateRecommendationAndStartObserving()
1399-
}
1400-
viewModel.analyticsServicesManager = deviceManager.analyticsServicesManager
1401-
let bolusEntryView = BolusEntryView(viewModel: viewModel).environmentObject(deviceManager.displayGlucosePreference)
1402-
hostingController = DismissibleHostingController(rootView: bolusEntryView, isModalInPresentation: false)
1400+
let viewModel: BolusEntryViewModel = {
1401+
let viewModel = BolusEntryViewModel(
1402+
delegate: deviceManager,
1403+
screenWidth: UIScreen.main.bounds.width,
1404+
isManualGlucoseEntryEnabled: enableManualGlucoseEntry
1405+
)
1406+
1407+
Task { @MainActor in
1408+
await viewModel.generateRecommendationAndStartObserving()
1409+
}
1410+
1411+
viewModel.analyticsServicesManager = deviceManager.analyticsServicesManager
1412+
1413+
return viewModel
1414+
}()
1415+
1416+
BolusEntryView(viewModel: viewModel)
1417+
.environmentObject(deviceManager.displayGlucosePreference)
14031418
}
1419+
}
1420+
1421+
func presentBolusEntryView(enableManualGlucoseEntry: Bool = false) {
1422+
let hostingController = DismissibleHostingController(
1423+
content: bolusEntryView(
1424+
enableManualGlucoseEntry: enableManualGlucoseEntry
1425+
)
1426+
)
1427+
14041428
let navigationWrapper = UINavigationController(rootViewController: hostingController)
14051429
hostingController.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: navigationWrapper, action: #selector(dismissWithAnimation))
14061430
present(navigationWrapper, animated: true)

Loop/Views/NotificationsCriticalAlertPermissionsView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ public struct NotificationsCriticalAlertPermissionsView: View {
3232

3333
public var body: some View {
3434
switch mode {
35-
case .flow: return AnyView(content())
36-
case .topLevel: return AnyView(navigationContent())
35+
case .flow: content()
36+
case .topLevel: navigationContent()
3737
}
3838
}
3939

Loop/Views/SettingsView.swift

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,13 @@ extension String: Identifiable {
119119
}
120120
}
121121

122-
struct PluginMenuItem: Identifiable {
122+
struct PluginMenuItem<Content: View>: Identifiable {
123123
var id: String {
124124
return pluginIdentifier + String(describing: offset)
125125
}
126126

127127
let section: SettingsMenuSection
128-
let view: AnyView
128+
let view: Content
129129
let pluginIdentifier: String
130130
let offset: Int
131131
}
@@ -206,7 +206,7 @@ extension SettingsView {
206206
Section(header: SectionHeader(label: NSLocalizedString("Configuration", comment: "The title of the Configuration section in settings"))) {
207207
LargeButton(action: { self.therapySettingsIsPresented = true },
208208
includeArrow: true,
209-
imageView: AnyView(Image("Therapy Icon")),
209+
imageView: Image("Therapy Icon"),
210210
label: NSLocalizedString("Therapy Settings", comment: "Title text for button to Therapy Settings"),
211211
descriptiveText: NSLocalizedString("Diabetes Treatment", comment: "Descriptive text for Therapy Settings"))
212212
.sheet(isPresented: $therapySettingsIsPresented) {
@@ -235,7 +235,7 @@ extension SettingsView {
235235
}
236236
}
237237

238-
private var pluginMenuItems: [PluginMenuItem] {
238+
private var pluginMenuItems: [PluginMenuItem<some View>] {
239239
self.viewModel.availableSupports.flatMap { plugin in
240240
plugin.configurationMenuItems().enumerated().map { index, item in
241241
PluginMenuItem(section: item.section, view: item.view, pluginIdentifier: plugin.identifier, offset: index)
@@ -261,7 +261,7 @@ extension SettingsView {
261261
} else if viewModel.isOnboardingComplete {
262262
LargeButton(action: { self.pumpChooserIsPresented = true },
263263
includeArrow: false,
264-
imageView: AnyView(plusImage),
264+
imageView: plusImage,
265265
label: NSLocalizedString("Add Pump", comment: "Title text for button to add pump device"),
266266
descriptiveText: NSLocalizedString("Tap here to set up a pump", comment: "Descriptive text for button to add pump device"))
267267
.actionSheet(isPresented: $pumpChooserIsPresented) {
@@ -293,7 +293,7 @@ extension SettingsView {
293293
} else {
294294
LargeButton(action: { self.cgmChooserIsPresented = true },
295295
includeArrow: false,
296-
imageView: AnyView(plusImage),
296+
imageView: plusImage,
297297
label: NSLocalizedString("Add CGM", comment: "Title text for button to add CGM device"),
298298
descriptiveText: NSLocalizedString("Tap here to set up a CGM", comment: "Descriptive text for button to add CGM device"))
299299
.actionSheet(isPresented: $cgmChooserIsPresented) {
@@ -306,7 +306,7 @@ extension SettingsView {
306306
Section {
307307
LargeButton(action: { self.favoriteFoodsIsPresented = true },
308308
includeArrow: true,
309-
imageView: AnyView(Image("Favorite Foods Icon").renderingMode(.template).foregroundColor(carbTintColor)),
309+
imageView: Image("Favorite Foods Icon").renderingMode(.template).foregroundColor(carbTintColor),
310310
label: "Favorite Foods",
311311
descriptiveText: "Simplify Carb Entry")
312312
}
@@ -339,7 +339,7 @@ extension SettingsView {
339339
if viewModel.servicesViewModel.inactiveServices().count > 0 {
340340
LargeButton(action: { self.serviceChooserIsPresented = true },
341341
includeArrow: false,
342-
imageView: AnyView(plusImage),
342+
imageView: plusImage,
343343
label: NSLocalizedString("Add Service", comment: "The title of the add service button in settings"),
344344
descriptiveText: NSLocalizedString("Tap here to set up a Service", comment: "The descriptive text of the add service button in settings"))
345345
.actionSheet(isPresented: $serviceChooserIsPresented) {
@@ -455,41 +455,43 @@ extension SettingsView {
455455
.padding(EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10))
456456
}
457457

458-
private func deviceImage(uiImage: UIImage?) -> AnyView {
458+
@ViewBuilder
459+
private func deviceImage(uiImage: UIImage?) -> some View {
459460
if let uiImage = uiImage {
460-
return AnyView(Image(uiImage: uiImage)
461+
Image(uiImage: uiImage)
461462
.renderingMode(.original)
462463
.resizable()
463-
.scaledToFit())
464+
.scaledToFit()
464465
} else {
465-
return AnyView(Spacer())
466+
Spacer()
466467
}
467468
}
468469

469-
private func serviceImage(uiImage: UIImage?) -> AnyView {
470-
return deviceImage(uiImage: uiImage)
470+
@ViewBuilder
471+
private func serviceImage(uiImage: UIImage?) -> some View {
472+
deviceImage(uiImage: uiImage)
471473
}
472474
}
473475

474-
fileprivate struct LargeButton: View {
476+
fileprivate struct LargeButton<Content: View>: View {
475477

476478
let action: () -> Void
477479
var includeArrow: Bool = true
478-
let imageView: AnyView
480+
let imageView: Content
479481
let label: String
480482
let descriptiveText: String
481483

482484
// TODO: The design doesn't show this, but do we need to consider different values here for different size classes?
483-
static let spacing: CGFloat = 15
484-
static let imageWidth: CGFloat = 60
485-
static let imageHeight: CGFloat = 60
486-
static let topBottomPadding: CGFloat = 10
485+
private let spacing: CGFloat = 15
486+
private let imageWidth: CGFloat = 60
487+
private let imageHeight: CGFloat = 60
488+
private let topBottomPadding: CGFloat = 10
487489

488490
public var body: some View {
489491
Button(action: action) {
490492
HStack {
491-
HStack(spacing: Self.spacing) {
492-
imageView.frame(width: Self.imageWidth, height: Self.imageHeight)
493+
HStack(spacing: spacing) {
494+
imageView.frame(width: imageWidth, height: imageHeight)
493495
VStack(alignment: .leading) {
494496
Text(label)
495497
.foregroundColor(.primary)
@@ -502,7 +504,7 @@ fileprivate struct LargeButton: View {
502504
Image(systemName: "chevron.right").foregroundColor(.gray).font(.footnote)
503505
}
504506
}
505-
.padding(EdgeInsets(top: Self.topBottomPadding, leading: 0, bottom: Self.topBottomPadding, trailing: 0))
507+
.padding(EdgeInsets(top: topBottomPadding, leading: 0, bottom: topBottomPadding, trailing: 0))
506508
}
507509
}
508510
}

LoopTests/Managers/SupportManagerTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ class SupportManagerTests: XCTestCase {
1616
enum MockError: Error { case nothing }
1717

1818
class Mixin {
19-
func supportMenuItem(supportInfoProvider: SupportInfoProvider, urlHandler: @escaping (URL) -> Void) -> AnyView? {
20-
nil
21-
}
19+
@ViewBuilder
20+
func supportMenuItem(supportInfoProvider: SupportInfoProvider, urlHandler: @escaping (URL) -> Void) -> some View {}
21+
2222
func softwareUpdateView(bundleIdentifier: String, currentVersion: String, guidanceColors: GuidanceColors, openAppStore: (() -> Void)?) -> AnyView? {
2323
nil
2424
}

LoopUI/Extensions/DismissibleHostingController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import SwiftUI
1010
import LoopKitUI
1111

1212
extension DismissibleHostingController {
13-
public convenience init<Content: View>(
13+
public convenience init(
1414
rootView: Content,
1515
dismissalMode: DismissalMode = .modalDismiss,
1616
isModalInPresentation: Bool = true,
1717
onDisappear: @escaping () -> Void = {}
1818
) {
19-
self.init(rootView: rootView,
19+
self.init(content: rootView,
2020
dismissalMode: dismissalMode,
2121
isModalInPresentation: isModalInPresentation,
2222
onDisappear: onDisappear,

0 commit comments

Comments
 (0)