Skip to content

Commit 1221595

Browse files
evil159github-actions[bot]
authored andcommitted
Weather radar use case (#6711)
This PR adds weather radar use case + adds search across all examples + adds settings tab with sdk version number. <img width="300" alt="Simulator Screenshot - iPhone 17 Pro - 2025-09-23 at 15 39 09" src="https://github.com/user-attachments/assets/49a7391f-f86d-44e4-8e4f-cfe56a8851e1" /> Work done in the scope of: https://mapbox.atlassian.net/browse/MAPSIOS-1954 cc @mapbox/maps-ios GitOrigin-RevId: 5f2c1765503312a08ce734d6b2feb51a0747f8a2
1 parent 737f26c commit 1221595

File tree

15 files changed

+1111
-107
lines changed

15 files changed

+1111
-107
lines changed

Examples.xcodeproj/project.pbxproj

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,16 @@
8282
7350DF212DFCC73A00B47542 /* MarkersExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7350DF1E2DFCC73A00B47542 /* MarkersExample.swift */; };
8383
7352DDB22DD7E9EE000E3000 /* StudioStyleExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7352DDB02DD7E9EE000E3000 /* StudioStyleExample.swift */; };
8484
7365170E39A459EB4DFA198B /* ExamplesUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE18E37A8652B4807D2459F1 /* ExamplesUITests.swift */; platformFilter = ios; };
85+
74661E732E82C77B00AB1288 /* ExamplesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74661E722E82C77B00AB1288 /* ExamplesSettingsView.swift */; };
8586
74C285362E7D4B0100A4A5B8 /* ExamplesRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C285352E7D4B0100A4A5B8 /* ExamplesRootView.swift */; };
8687
74C285502E7D4B1800A4A5B8 /* style.json in Resources */ = {isa = PBXBuildFile; fileRef = 74C285462E7D4B1800A4A5B8 /* style.json */; };
8788
74C285512E7D4B1800A4A5B8 /* VisitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2853F2E7D4B1800A4A5B8 /* VisitManager.swift */; };
8889
74C285522E7D4B1800A4A5B8 /* PinPoweredMapConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C285382E7D4B1800A4A5B8 /* PinPoweredMapConstants.swift */; };
90+
74C285532E7D4B1800A4A5B8 /* ColorPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C285482E7D4B1800A4A5B8 /* ColorPaletteView.swift */; };
91+
74C285542E7D4B1800A4A5B8 /* RadarContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2854B2E7D4B1800A4A5B8 /* RadarContentView.swift */; };
92+
74C285552E7D4B1800A4A5B8 /* RadarExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2854C2E7D4B1800A4A5B8 /* RadarExtensions.swift */; };
8993
74C285562E7D4B1800A4A5B8 /* POICategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2853E2E7D4B1800A4A5B8 /* POICategory.swift */; };
94+
74C285572E7D4B1800A4A5B8 /* ColorScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C285492E7D4B1800A4A5B8 /* ColorScheme.swift */; };
9095
74C285582E7D4B1800A4A5B8 /* FeatureDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2853B2E7D4B1800A4A5B8 /* FeatureDetails.swift */; };
9196
74C285592E7D4B1800A4A5B8 /* FavoritesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2853A2E7D4B1800A4A5B8 /* FavoritesManager.swift */; };
9297
74C2855A2E7D4B1800A4A5B8 /* FilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C285432E7D4B1800A4A5B8 /* FilterView.swift */; };
@@ -96,7 +101,9 @@
96101
74C2855E2E7D4B1800A4A5B8 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C285372E7D4B1800A4A5B8 /* Extensions.swift */; };
97102
74C2855F2E7D4B1800A4A5B8 /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2853C2E7D4B1800A4A5B8 /* NetworkService.swift */; };
98103
74C285602E7D4B1800A4A5B8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C285412E7D4B1800A4A5B8 /* ContentView.swift */; };
104+
74C285612E7D4B1800A4A5B8 /* TimelineScrubber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2854A2E7D4B1800A4A5B8 /* TimelineScrubber.swift */; };
99105
74C285622E7D4B1800A4A5B8 /* UseCasesRoot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C2854E2E7D4B1800A4A5B8 /* UseCasesRoot.swift */; };
106+
74E391302E815E9600455614 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74E3912F2E815E9600455614 /* SearchView.swift */; };
100107
759D42AA5FE93B6FA9DFADF5 /* LocationOverrideExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45B39AE24486FED5ED30392D /* LocationOverrideExample.swift */; };
101108
7686448F8648BECC75A912B6 /* DashboardCarPlaySceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 913B4773A82AD6357D6AAEA1 /* DashboardCarPlaySceneDelegate.swift */; platformFilter = ios; };
102109
79843B780E7C5DC68433B745 /* SnapshotMapExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC5A8729C9AEA4711B56B5F0 /* SnapshotMapExample.swift */; };
@@ -275,6 +282,7 @@
275282
7350DF1E2DFCC73A00B47542 /* MarkersExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkersExample.swift; sourceTree = "<group>"; };
276283
7352DDB02DD7E9EE000E3000 /* StudioStyleExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudioStyleExample.swift; sourceTree = "<group>"; };
277284
7352DDB42DDB93B5000E3000 /* StudioStyleExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StudioStyleExample.swift; path = "Sources/Examples/SwiftUI Examples/Testing Examples/StudioStyleExample.swift"; sourceTree = "<group>"; };
285+
74661E722E82C77B00AB1288 /* ExamplesSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExamplesSettingsView.swift; sourceTree = "<group>"; };
278286
74C285352E7D4B0100A4A5B8 /* ExamplesRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExamplesRootView.swift; sourceTree = "<group>"; };
279287
74C285372E7D4B1800A4A5B8 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
280288
74C285382E7D4B1800A4A5B8 /* PinPoweredMapConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinPoweredMapConstants.swift; sourceTree = "<group>"; };
@@ -289,7 +297,13 @@
289297
74C285432E7D4B1800A4A5B8 /* FilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterView.swift; sourceTree = "<group>"; };
290298
74C285442E7D4B1800A4A5B8 /* SegmentedToggleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedToggleView.swift; sourceTree = "<group>"; };
291299
74C285462E7D4B1800A4A5B8 /* style.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = style.json; sourceTree = "<group>"; };
300+
74C285482E7D4B1800A4A5B8 /* ColorPaletteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPaletteView.swift; sourceTree = "<group>"; };
301+
74C285492E7D4B1800A4A5B8 /* ColorScheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorScheme.swift; sourceTree = "<group>"; };
302+
74C2854A2E7D4B1800A4A5B8 /* TimelineScrubber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineScrubber.swift; sourceTree = "<group>"; };
303+
74C2854B2E7D4B1800A4A5B8 /* RadarContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadarContentView.swift; sourceTree = "<group>"; };
304+
74C2854C2E7D4B1800A4A5B8 /* RadarExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadarExtensions.swift; sourceTree = "<group>"; };
292305
74C2854E2E7D4B1800A4A5B8 /* UseCasesRoot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UseCasesRoot.swift; sourceTree = "<group>"; };
306+
74E3912F2E815E9600455614 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
293307
75D03F5A3A0E879717BFE421 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
294308
7613C4E19DCD679A2620223C /* GeofencingPlayground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeofencingPlayground.swift; sourceTree = "<group>"; };
295309
78811E5A3185D2D32495870A /* SimpleMapExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMapExample.swift; sourceTree = "<group>"; };
@@ -432,7 +446,9 @@
432446
EC1155178B21E2E8075454A8 /* Info.plist */,
433447
55FDF5B3329BFD6E6C346D80 /* LaunchScreen.storyboard */,
434448
96B0E9086FE939F5D723136D /* VisionOSMain.swift */,
449+
74E3912F2E815E9600455614 /* SearchView.swift */,
435450
74C285352E7D4B0100A4A5B8 /* ExamplesRootView.swift */,
451+
74661E722E82C77B00AB1288 /* ExamplesSettingsView.swift */,
436452
ACB753539ABAD3312B849CB1 /* All Examples */,
437453
43EC579EBDA110D1E1B3E494 /* Controllers */,
438454
9AC6F30FB33614908581AE8E /* Extensions */,
@@ -534,10 +550,23 @@
534550
path = PinPoweredMap;
535551
sourceTree = "<group>";
536552
};
553+
74C2854D2E7D4B1800A4A5B8 /* WeatherRadar */ = {
554+
isa = PBXGroup;
555+
children = (
556+
74C285482E7D4B1800A4A5B8 /* ColorPaletteView.swift */,
557+
74C285492E7D4B1800A4A5B8 /* ColorScheme.swift */,
558+
74C2854A2E7D4B1800A4A5B8 /* TimelineScrubber.swift */,
559+
74C2854B2E7D4B1800A4A5B8 /* RadarContentView.swift */,
560+
74C2854C2E7D4B1800A4A5B8 /* RadarExtensions.swift */,
561+
);
562+
path = WeatherRadar;
563+
sourceTree = "<group>";
564+
};
537565
74C2854F2E7D4B1800A4A5B8 /* UseCases */ = {
538566
isa = PBXGroup;
539567
children = (
540568
74C285472E7D4B1800A4A5B8 /* PinPoweredMap */,
569+
74C2854D2E7D4B1800A4A5B8 /* WeatherRadar */,
541570
74C2854E2E7D4B1800A4A5B8 /* UseCasesRoot.swift */,
542571
);
543572
path = UseCases;
@@ -960,7 +989,11 @@
960989
821807D61D52F0E60925BCD4 /* CameraAnimationExample.swift in Sources */,
961990
74C285512E7D4B1800A4A5B8 /* VisitManager.swift in Sources */,
962991
74C285522E7D4B1800A4A5B8 /* PinPoweredMapConstants.swift in Sources */,
992+
74C285532E7D4B1800A4A5B8 /* ColorPaletteView.swift in Sources */,
993+
74C285542E7D4B1800A4A5B8 /* RadarContentView.swift in Sources */,
994+
74C285552E7D4B1800A4A5B8 /* RadarExtensions.swift in Sources */,
963995
74C285562E7D4B1800A4A5B8 /* POICategory.swift in Sources */,
996+
74C285572E7D4B1800A4A5B8 /* ColorScheme.swift in Sources */,
964997
74C285582E7D4B1800A4A5B8 /* FeatureDetails.swift in Sources */,
965998
74C285592E7D4B1800A4A5B8 /* FavoritesManager.swift in Sources */,
966999
74C2855A2E7D4B1800A4A5B8 /* FilterView.swift in Sources */,
@@ -970,8 +1003,10 @@
9701003
74C2855E2E7D4B1800A4A5B8 /* Extensions.swift in Sources */,
9711004
74C2855F2E7D4B1800A4A5B8 /* NetworkService.swift in Sources */,
9721005
74C285602E7D4B1800A4A5B8 /* ContentView.swift in Sources */,
1006+
74C285612E7D4B1800A4A5B8 /* TimelineScrubber.swift in Sources */,
9731007
74C285622E7D4B1800A4A5B8 /* UseCasesRoot.swift in Sources */,
9741008
9A403D6AB6D6336E212726C5 /* CameraAnimatorsExample.swift in Sources */,
1009+
74E391302E815E9600455614 /* SearchView.swift in Sources */,
9751010
33B816803AF5330796686AA1 /* CameraForExample.swift in Sources */,
9761011
F0502A1ACF0AED218F8184AB /* CarPlayMapViewController.swift in Sources */,
9771012
CA2209956E93ECB18C4C9DEC /* CircleAnnotationExample.swift in Sources */,
@@ -1034,6 +1069,7 @@
10341069
D94672F30272E31087AB5DDD /* NavigationSimulator.swift in Sources */,
10351070
902FD51EC410A1E8BD88941D /* NavigationSimulatorExample.swift in Sources */,
10361071
E6B722A64C15CE701287B464 /* OfflineManagerExample.swift in Sources */,
1072+
74661E732E82C77B00AB1288 /* ExamplesSettingsView.swift in Sources */,
10371073
5FF3E34B523C39A404154BF7 /* OfflineRegionManagerExample.swift in Sources */,
10381074
312CE7CED726F0A572301622 /* PinView.swift in Sources */,
10391075
A6389C28B8AAC39878591AD0 /* PitchAndDistanceExample.swift in Sources */,

Sources/Examples/AppDelegate.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
3131
appearance.prefersLargeTitles = true
3232
appearance.scrollEdgeAppearance = UINavigationBarAppearance()
3333

34+
let tabBarAppearance = UITabBarAppearance()
35+
tabBarAppearance.configureWithOpaqueBackground()
36+
37+
38+
UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
39+
3440
return true
3541
}
3642
}

Sources/Examples/Controllers/ExampleTableViewController.swift

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,12 @@ final class ExampleTableViewController: UITableViewController {
1515
super.viewDidLoad()
1616
title = "UIKit Examples"
1717

18-
let searchController = UISearchController(searchResultsController: nil)
19-
searchController.searchResultsUpdater = self
20-
searchController.searchBar.placeholder = "Search"
21-
searchController.obscuresBackgroundDuringPresentation = false
22-
navigationItem.searchController = searchController
23-
24-
if #available(iOS 26.0, *) {
25-
#if compiler(>=6.2)
26-
self.navigationItem.subtitle = Bundle.mapboxMapsMetadata.version
27-
#endif
28-
} else {
29-
var version = Bundle.mapboxMapsMetadata.version
30-
if version.count > 12 {
31-
version = version.prefix(12) + "..."
32-
}
33-
let versionButton = UIBarButtonItem(title: version, image: nil, target: self, action: #selector(openVersion))
34-
navigationItem.rightBarButtonItem = versionButton
18+
if #unavailable(iOS 18.0) {
19+
let searchController = UISearchController(searchResultsController: nil)
20+
searchController.searchResultsUpdater = self
21+
searchController.searchBar.placeholder = "Search"
22+
searchController.obscuresBackgroundDuringPresentation = false
23+
navigationItem.searchController = searchController
3524
}
3625

3726
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "reuseIdentifier")
@@ -62,13 +51,6 @@ final class ExampleTableViewController: UITableViewController {
6251
UserDefaults.standard.removeObject(forKey: startingExampleTitleKey)
6352
}
6453

65-
@objc func openVersion() {
66-
let str = "MapboxMaps: \(Bundle.mapboxMapsMetadata.version)"
67-
let vc = UIAlertController(title: "Version", message: str, preferredStyle: .alert)
68-
vc.addAction(UIAlertAction(title: "OK", style: .default))
69-
present(vc, animated: true)
70-
}
71-
7254
override func viewWillAppear(_ animated: Bool) {
7355
super.viewWillAppear(animated)
7456
navigationController?.setToolbarHidden(true, animated: false)

Sources/Examples/ExamplesRootView.swift

Lines changed: 85 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,95 @@ import SwiftUI
22
import UIKit
33

44
struct ExamplesRootView: View {
5+
@State private var searchText: String = ""
6+
7+
// MARK: - Tab Content
8+
private var uikitTab: some View {
9+
UIKitExampleView(vc: UINavigationController(rootViewController: ExampleTableViewController(style: .insetGrouped)), title: "UIKit")
10+
.ignoresSafeArea()
11+
}
12+
13+
private var swiftUITab: some View {
14+
SwiftUIWrapper()
15+
}
16+
17+
private var useCasesTab: some View {
18+
UseCasesRoot()
19+
}
20+
21+
private var settingsTab: some View {
22+
ExamplesSettingsView()
23+
}
24+
25+
private var searchTab: some View {
26+
SearchView(searchText: $searchText)
27+
.searchable(text: $searchText)
28+
}
29+
530
var body: some View {
31+
if #available(iOS 18.0, *) {
32+
modernTabView
33+
.safeTabBarMinimizeBehaviorOnScrollDown()
34+
} else {
35+
legacyTabView
36+
.safeTabBarMinimizeBehaviorOnScrollDown()
37+
}
38+
}
39+
40+
// MARK: - Modern Tab View (iOS 18+)
41+
@available(iOS 18.0, *)
42+
private var modernTabView: some View {
643
TabView {
7-
UIKitExamplesView()
8-
.ignoresSafeArea()
44+
Tab("UIKit", systemImage: "hammer") {
45+
uikitTab
46+
}
47+
48+
Tab("SwiftUI", systemImage: "swift") {
49+
swiftUITab
50+
}
51+
52+
Tab("Use Cases", systemImage: "book") {
53+
useCasesTab
54+
}
55+
56+
Tab("Settings", systemImage: "gear") {
57+
settingsTab
58+
}
59+
60+
Tab(role: .search) {
61+
searchTab
62+
}
63+
}
64+
.tabViewStyle(.sidebarAdaptable)
65+
}
66+
67+
// MARK: - Legacy Tab View
68+
private var legacyTabView: some View {
69+
TabView {
70+
uikitTab
971
.tabItem {
1072
Image(systemName: "hammer")
1173
Text("UIKit")
1274
}
1375

14-
SwiftUIWrapper()
76+
swiftUITab
1577
.tabItem {
1678
Image(systemName: "swift")
1779
Text("SwiftUI")
1880
}
1981

20-
UseCasesRoot()
82+
useCasesTab
2183
.tabItem {
2284
Image(systemName: "book")
2385
Text("Use Cases")
2486
}
87+
88+
settingsTab
89+
.tabItem {
90+
Image(systemName: "gear")
91+
Text("Settings")
92+
}
2593
}
26-
.safeTabBarMinimizeBehaviorOnScrollDown()
2794
}
2895
}
2996

@@ -36,23 +103,24 @@ extension View {
36103
#endif
37104
return self
38105
}
106+
}
39107

40-
func safeNavigationSubtitle(_ subtitle: String) -> some View {
41-
#if compiler(>=6.2)
42-
if #available(iOS 26.0, *) {
43-
return self.navigationSubtitle(subtitle)
44-
}
45-
#endif
46-
return self
108+
struct UIKitExampleView: UIViewControllerRepresentable {
109+
private var vc: () -> UIViewController
110+
private var title: String
111+
112+
init(vc: @escaping @autoclosure () -> UIViewController, title: String) {
113+
self.vc = vc
114+
self.title = title
47115
}
48-
}
49116

50-
struct UIKitExamplesView: UIViewControllerRepresentable {
51-
func makeUIViewController(context: Context) -> UINavigationController {
52-
return UINavigationController(rootViewController: ExampleTableViewController(style: .insetGrouped))
117+
func makeUIViewController(context: Context) -> UIViewController {
118+
let vc = vc()
119+
vc.title = title
120+
return vc
53121
}
54122

55-
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
123+
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
56124
// No updates needed
57125
}
58126
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import SwiftUI
2+
@_spi(Internal) import MapboxMaps
3+
4+
struct ExamplesSettingsView: View {
5+
var body: some View {
6+
NavigationStack {
7+
List {
8+
Section("Maps SDK") {
9+
ViewThatFits {
10+
// Try horizontal layout first
11+
HStack {
12+
Text("Version")
13+
Spacer()
14+
Text(Bundle.mapboxMapsMetadata.version)
15+
.foregroundColor(.secondary)
16+
}
17+
18+
// Fall back to vertical layout if horizontal doesn't fit
19+
VStack(alignment: .leading, spacing: 4) {
20+
Text("Version")
21+
Text(Bundle.mapboxMapsMetadata.version)
22+
.foregroundColor(.secondary)
23+
.font(.caption)
24+
}
25+
}
26+
}
27+
}
28+
.navigationTitle("Settings")
29+
}
30+
}
31+
}
32+
33+
#Preview {
34+
ExamplesSettingsView()
35+
}

0 commit comments

Comments
 (0)