├── .gitignore ├── ActionableViewModel ├── ActionableViewModel.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ActionableViewModel │ ├── Actionable.swift │ ├── ActionableViewModelApp.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── Feature │ │ ├── About │ │ │ └── AboutCoordinatorView.swift │ │ ├── Main │ │ │ ├── Enrollment │ │ │ │ └── EnrollmentCoordinatorView.swift │ │ │ ├── Home │ │ │ │ ├── HomeCoordinatorView.swift │ │ │ │ ├── HomeView.swift │ │ │ │ └── Profile │ │ │ │ │ └── ProfileView.swift │ │ │ ├── MainCoordinatorView.swift │ │ │ ├── More │ │ │ │ ├── Details │ │ │ │ │ └── DetailsView.swift │ │ │ │ ├── MoreCoordinatorView.swift │ │ │ │ └── MoreView.swift │ │ │ └── Settings │ │ │ │ └── SettingsCoordinatorView.swift │ │ ├── Onboarding │ │ │ └── OnboardingCoordinatorView.swift │ │ └── RootCoordinatorView.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json └── README.md ├── AlternateAppIcon ├── AlternateAppIcon.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── AlternateAppIcon │ ├── AlternateAppIconApp.swift │ ├── AppDelegate.swift │ ├── AppInfoProvider.swift │ ├── Application.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── Blue Green.appiconset │ │ │ ├── Contents.json │ │ │ └── Icon BlueGreen.png │ │ ├── Blue Red.appiconset │ │ │ ├── Contents.json │ │ │ └── Icon BlueRed.png │ │ ├── Contents.json │ │ ├── Green Red.appiconset │ │ │ ├── Contents.json │ │ │ └── Icon GreenRed.png │ │ └── Red Blue.appiconset │ │ │ ├── Contents.json │ │ │ └── Icon RedBlue.png │ ├── ContentView+ViewModel.swift │ ├── ContentView.swift │ ├── Dependencies.swift │ └── Preview Content │ │ ├── MockAppInfoProvider.swift │ │ ├── MockApplication.swift │ │ ├── MockDependencies.swift │ │ └── Preview Assets.xcassets │ │ └── Contents.json └── README.md ├── BLEChat ├── BLEChat.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ └── xcshareddata │ │ └── xcschemes │ │ └── BLEChat.xcscheme ├── BLEChat │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Bluetooth │ │ ├── AssignedNumbers.swift │ │ ├── BluetoothError.swift │ │ ├── ChatHost │ │ │ ├── ChatHost.swift │ │ │ ├── ChatServiceFactory.swift │ │ │ └── CoreBluetoothChatHost.swift │ │ └── ChatHostScanner │ │ │ ├── ChatHostConnection.swift │ │ │ ├── ChatHostScanner.swift │ │ │ ├── CoreBluetoothChatHostConnection.swift │ │ │ └── CoreBluetoothChatHostScanner.swift │ ├── Dependencies.swift │ ├── Features │ │ ├── Guest │ │ │ ├── GuestChatViewController.swift │ │ │ └── JoinViewController.swift │ │ ├── HomeViewController.swift │ │ ├── Host │ │ │ └── HostChatViewController.swift │ │ └── Shared │ │ │ ├── ChatBubbleTableViewCell.swift │ │ │ └── ChatSection.swift │ ├── Info.plist │ ├── SceneDelegate.swift │ └── Utils │ │ └── StopRunLoopSource.swift └── README.md ├── BackgroundCleanup ├── BackgroundCleanup.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── BackgroundCleanup.xcscheme ├── BackgroundCleanup │ ├── App │ │ ├── AppDelegate.swift │ │ ├── AppDependencies.swift │ │ ├── DefaultAppDependencies.swift │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ └── UIApplication+Application.swift │ ├── Common │ │ ├── Models │ │ │ └── Item.swift │ │ ├── Repositories │ │ │ └── ItemRepository.swift │ │ └── Services │ │ │ ├── CleanupService.swift │ │ │ └── RefreshService.swift │ ├── Features │ │ ├── ItemsViewController.swift │ │ └── ItemsViewModel.swift │ └── Resources │ │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ └── Base.lproj │ │ └── LaunchScreen.storyboard └── README.md ├── BottomSheetController ├── BottomSheetController.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── BottomSheetController │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── BottomSheet │ │ ├── BottomSheetController.swift │ │ ├── BottomSheetInteractiveDismissalTransition.swift │ │ ├── BottomSheetPresentationController.swift │ │ └── BottomSheetTransitioningDelegate.swift │ ├── DenseContentSheetViewController.swift │ ├── ExpandingContentSheetViewController.swift │ ├── Info.plist │ ├── LifecycleDependentContentSheetViewController.swift │ ├── SceneDelegate.swift │ ├── SparseContentSheetViewController.swift │ ├── TableContentSheetViewController.swift │ └── ViewController.swift └── README.md ├── BuildConfigurations ├── BuildConfigurations.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ ├── BuildConfigurations Prod.xcscheme │ │ ├── BuildConfigurations-Develop.xcscheme │ │ └── BuildConfigurations-Test.xcscheme ├── BuildConfigurations │ ├── App │ │ ├── BuildConfigurationsApp.swift │ │ └── ContentView.swift │ ├── Flavours │ │ ├── Develop │ │ │ ├── ConstantsDevelop.swift │ │ │ └── Properties.plist │ │ ├── Prod │ │ │ ├── ConstantsProd.swift │ │ │ └── Properties.plist │ │ ├── Properties.plist │ │ └── Test │ │ │ ├── ConstantsTest.swift │ │ │ └── Properties.plist │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ └── Resources │ │ └── Assets.xcassets │ │ ├── AccentColor.colorset │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ └── Contents.json │ │ └── Contents.json └── README.md ├── ConsecutiveTabTaps ├── ConsecutiveTabTaps.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ConsecutiveTabTaps │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ConsecutiveTabTapsApp.swift │ ├── Countries │ │ ├── CountriesView.swift │ │ ├── CountriesViewModel.swift │ │ ├── Country.swift │ │ └── Country │ │ │ └── CountryView.swift │ ├── MainView.swift │ ├── MainViewModel.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ └── String+emojiFlag.swift └── README.md ├── ContainerViewController ├── ContainerViewController.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved ├── ContainerViewController │ ├── App │ │ ├── AppDelegate.swift │ │ ├── AppDependencies.swift │ │ ├── AppFlowController.swift │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ └── SceneFlowController.swift │ ├── Common │ │ ├── SegmentedPageController.swift │ │ └── SinglePageController.swift │ ├── Features │ │ ├── Login │ │ │ ├── Login │ │ │ │ ├── LoginViewController.swift │ │ │ │ └── LoginViewModel.swift │ │ │ ├── LoginFlowController.swift │ │ │ └── Registration │ │ │ │ ├── RegisterViewController.swift │ │ │ │ └── RegisterViewModel.swift │ │ ├── Main │ │ │ ├── Activity │ │ │ │ ├── ActivityFlowController.swift │ │ │ │ └── ActivityViewController.swift │ │ │ ├── Home │ │ │ │ ├── Feed │ │ │ │ │ ├── FeedFlowController.swift │ │ │ │ │ ├── New │ │ │ │ │ │ └── NewsViewController.swift │ │ │ │ │ └── Popular │ │ │ │ │ │ └── PopularViewController.swift │ │ │ │ ├── HomeFlowController.swift │ │ │ │ └── HomeViewController.swift │ │ │ ├── MainFlowController.swift │ │ │ └── Profile │ │ │ │ ├── ProfileFlowController.swift │ │ │ │ ├── ProfileViewController.swift │ │ │ │ └── ProfileViewModel.swift │ │ └── Onboarding │ │ │ ├── OnboardingFlowController.swift │ │ │ ├── OnboardingViewController.swift │ │ │ └── OnboardingViewModel.swift │ └── Resources │ │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ └── LaunchScreen.storyboard └── README.md ├── CustomInterfaceBuilderView ├── CustomInterfaceBuilderView.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── CustomInterfaceBuilderView │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── CircularView.swift │ ├── Info.plist │ ├── RatingView.swift │ ├── RoundedView.swift │ ├── SceneDelegate.swift │ └── ViewController.swift └── README.md ├── CustomPresentationController ├── CustomPresentationController.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── CustomPresentationController │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── fruit.imageset │ │ │ ├── Contents.json │ │ │ └── fruit.jpeg │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── ContentViewController.swift │ ├── DialogTransitionManager.swift │ ├── Info.plist │ ├── MotionEffectsViewController.swift │ ├── SceneDelegate.swift │ ├── ShelfTransitionManager.swift │ ├── ViewController.swift │ └── VisualEffectsViewController.swift └── README.md ├── DialogController ├── DialogController.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── DialogController │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Dialog │ │ ├── DialogController.swift │ │ └── DialogTransitioningDelegate.swift │ ├── ExpandableDialogController.swift │ ├── FormDialogController.swift │ ├── Info.plist │ ├── OkCancelDialogController.swift │ ├── OkDialogController.swift │ ├── SceneDelegate.swift │ └── ViewController.swift └── README.md ├── DynamicAnimations ├── DynamicAnimations.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── DynamicAnimations │ ├── App │ │ ├── AppDelegate.swift │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ └── TabBarController.swift │ ├── Behaviors │ │ ├── AttachmentBehaviorViewController.swift │ │ ├── CollisionBehaviorViewController.swift │ │ ├── FieldBehaviorViewController.swift │ │ ├── PushBehaviorViewController.swift │ │ └── SnapBehaviorViewController.swift │ ├── Common │ │ └── BallView.swift │ └── Resources │ │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ └── Base.lproj │ │ └── LaunchScreen.storyboard └── README.md ├── DynamicTableHeaderView ├── DynamicTableHeaderView.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── DynamicTableHeaderView │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── episode3.imageset │ │ │ ├── Contents.json │ │ │ └── episode3.png │ │ ├── episode4.imageset │ │ │ ├── Contents.json │ │ │ └── episode4.png │ │ ├── episode5.imageset │ │ │ ├── Contents.json │ │ │ └── episode5.png │ │ ├── episode6.imageset │ │ │ ├── Contents.json │ │ │ └── episode6.png │ │ ├── episode7.imageset │ │ │ ├── Contents.json │ │ │ └── episode7.png │ │ ├── episode8.imageset │ │ │ ├── Contents.json │ │ │ └── episode8.png │ │ ├── episode9.imageset │ │ │ ├── Contents.json │ │ │ └── episode9.png │ │ └── luke.imageset │ │ │ ├── Contents.json │ │ │ └── luke.png │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ ├── TableFooterView.swift │ ├── TableHeaderView.swift │ └── TableViewController.swift └── README.md ├── ErrorResponder ├── ErrorResponder.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── ErrorResponder │ ├── App │ │ ├── BackgroundService.swift │ │ └── ErrorResponderApp.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Common │ │ └── HTTPAPIProblem.swift │ ├── ErrorResponder.swift │ ├── ErrorResponderChain.swift │ ├── ErrorResponderViewModel.swift │ ├── Feature │ │ ├── CommonError.swift │ │ ├── FeatureOne │ │ │ ├── FeatureOneCoordinatorView+ViewModel.swift │ │ │ ├── FeatureOneCoordinatorView.swift │ │ │ ├── FeatureOneError.swift │ │ │ └── PageOne │ │ │ │ ├── PageOneFeatureOneError.swift │ │ │ │ ├── PageOneFeatureOneView+ViewModel.swift │ │ │ │ └── PageOneFeatureOneView.swift │ │ ├── FeatureThree │ │ │ ├── FeatureThreeCoordinatorView.swift │ │ │ └── PageOne │ │ │ │ └── PageOneFeatureThreeView.swift │ │ ├── FeatureTwo │ │ │ ├── FeatureTwoCoordinatorView+ViewModel.swift │ │ │ ├── FeatureTwoCoordinatorView.swift │ │ │ ├── FeatureTwoError.swift │ │ │ └── PageOne │ │ │ │ ├── PageOneFeatureTwoError.swift │ │ │ │ ├── PageOneFeatureTwoView+ViewModel.swift │ │ │ │ └── PageOneFeatureTwoView.swift │ │ ├── RootCoordinatorView+ViewModel.swift │ │ └── RootCoordinatorView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ └── View+AlertDetails.swift └── README.md ├── ExpandableTableViewCell ├── ExpandableTableViewCell.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ExpandableTableViewCell │ ├── Accordion │ │ ├── AccordionTableViewCell.swift │ │ └── AccordionTableViewController.swift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Details │ │ ├── DetailsTableViewCell.swift │ │ └── DetailsTableViewController.swift │ ├── ExpandableTableViewCellDelegate.swift │ ├── HeaderView.swift │ ├── Info.plist │ ├── SceneDelegate.swift │ └── TabBarViewController.swift └── README.md ├── ExtendedSplashScreen ├── ExtendedSplashScreen.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ExtendedSplashScreen │ ├── AppBlockedViewController.swift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── DeviceManager.swift │ ├── Info.plist │ ├── MainViewController.swift │ ├── RootViewController.swift │ ├── SceneDelegate.swift │ └── SplashScreenViewController.swift └── README.md ├── FeatureModules ├── CoreKit │ ├── .gitignore │ ├── Package.swift │ ├── README.md │ └── Sources │ │ └── CoreKit │ │ └── Coordinator.swift ├── FeatureModules.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── FeatureModules │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ └── TabBarController.swift ├── FeatureOneKit │ ├── .gitignore │ ├── Package.swift │ ├── README.md │ └── Sources │ │ └── FeatureOneKit │ │ ├── FeatureOneCoordinator.swift │ │ └── FeatureOneViewController.swift ├── FeatureThreeKit │ ├── .gitignore │ ├── Package.swift │ ├── README.md │ └── Sources │ │ └── FeatureThreeKit │ │ ├── CustomNavigationController.swift │ │ ├── FeatureThreeCoordinator.swift │ │ └── FeatureThreeViewController.swift ├── FeatureTwoKit │ ├── .gitignore │ ├── Package.swift │ ├── README.md │ └── Sources │ │ └── FeatureTwoKit │ │ ├── FeatureTwoCoordinator.swift │ │ └── FeatureTwoViewController.swift └── README.md ├── FlowControllerPattern ├── ExamplePush.apns ├── FlowControllerPattern.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── FlowControllerPattern.xcscheme ├── FlowControllerPattern │ ├── App │ │ ├── AppDelegate.swift │ │ ├── AppDependencies.swift │ │ ├── AppFlowFactory.swift │ │ ├── AppFlowHost+AppFlowController.swift │ │ ├── AppPage.swift │ │ ├── Base.lproj │ │ │ └── LaunchScreen.storyboard │ │ ├── DefaultAppDependencies.swift │ │ ├── DefaultAppFlowFactory.swift │ │ ├── DefaultAppFlowHost.swift │ │ ├── FlowControllerPattern.entitlements │ │ └── Info.plist │ ├── Common │ │ ├── Configuration │ │ │ ├── App │ │ │ │ ├── AppConfiguration.swift │ │ │ │ └── DefaultAppConfiguration.swift │ │ │ └── Remote │ │ │ │ ├── DefaultRemoteConfiguration.swift │ │ │ │ └── RemoteConfiguration.swift │ │ ├── Models │ │ │ ├── ShoppingCart │ │ │ │ └── ShoppingCart.swift │ │ │ └── Store │ │ │ │ └── Store.swift │ │ ├── Networking │ │ │ └── Core │ │ │ │ ├── DefaultNetworkClient.swift │ │ │ │ ├── NetworkClient.swift │ │ │ │ ├── Request+Endpoint.swift │ │ │ │ ├── Request.swift │ │ │ │ └── RequestBuilder.swift │ │ ├── Repositories │ │ │ └── Defaults │ │ │ │ ├── DefaultDefaultsRepository.swift │ │ │ │ └── DefaultsRepository.swift │ │ ├── Services │ │ │ ├── Analytics │ │ │ │ ├── AnalyticsLogger.swift │ │ │ │ └── DefaultAnalyticsLogger.swift │ │ │ ├── Booking │ │ │ │ ├── BookingService.swift │ │ │ │ └── DefaultBookingService.swift │ │ │ ├── Crashlytics │ │ │ │ ├── CrashlyticsRecorder.swift │ │ │ │ └── DefaultCrashlyticsRecorder.swift │ │ │ └── Store │ │ │ │ ├── DefaultStoreService.swift │ │ │ │ └── StoreService.swift │ │ └── ViewControllers │ │ │ ├── SegmentedPageController.swift │ │ │ └── SinglePageController.swift │ ├── Resources │ │ └── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ │ └── Contents.json │ └── Scenes │ │ ├── Extractor.swift │ │ ├── Primary │ │ ├── AppPage+Primary.swift │ │ ├── DefaultPrimarySceneFlowHost.swift │ │ ├── Features │ │ │ ├── Main │ │ │ │ ├── Activity │ │ │ │ │ ├── ActivityFlowFactory.swift │ │ │ │ │ ├── ActivityFlowHost+ActivityFlowController.swift │ │ │ │ │ ├── DefaultActivityFlowHost.swift │ │ │ │ │ └── Purchases │ │ │ │ │ │ ├── DefaultPurchasesFlowHost.swift │ │ │ │ │ │ └── PurchasesFlowHost+PurchasesFlowController.swift │ │ │ │ ├── Booking │ │ │ │ │ ├── BookingFlowFactory.swift │ │ │ │ │ ├── BookingFlowHost+BookingFlowController.swift │ │ │ │ │ ├── Checkout │ │ │ │ │ │ ├── CheckoutViewController.swift │ │ │ │ │ │ └── CheckoutViewModel.swift │ │ │ │ │ ├── DefaultBookingFlowHost.swift │ │ │ │ │ └── Store │ │ │ │ │ │ ├── StoreViewController.swift │ │ │ │ │ │ └── StoreViewModel.swift │ │ │ │ ├── DefaultMainFlowController.swift │ │ │ │ ├── Explore │ │ │ │ │ ├── DefaultExploreFlowHost.swift │ │ │ │ │ ├── ExploreFlowFactory.swift │ │ │ │ │ ├── ExploreFlowHost+ExploreFlowController.swift │ │ │ │ │ ├── Referral │ │ │ │ │ │ └── ReferralViewController.swift │ │ │ │ │ └── Store │ │ │ │ │ │ ├── DefaultStoreFlowHost.swift │ │ │ │ │ │ ├── List │ │ │ │ │ │ ├── StoreListView.swift │ │ │ │ │ │ ├── StoreListViewController.swift │ │ │ │ │ │ └── StoreListViewModel.swift │ │ │ │ │ │ ├── Map │ │ │ │ │ │ ├── StoreMapView.swift │ │ │ │ │ │ └── StoreMapViewController.swift │ │ │ │ │ │ ├── StoreFilterSheet │ │ │ │ │ │ └── StoreFilterSheetController.swift │ │ │ │ │ │ ├── StoreFlowFactory.swift │ │ │ │ │ │ ├── StoreFlowHost+StoreFlowController.swift │ │ │ │ │ │ └── StoreFlowModels.swift │ │ │ │ ├── MainFlowFactory.swift │ │ │ │ ├── MainFlowHost+MainFlowController.swift │ │ │ │ └── Profile │ │ │ │ │ ├── DefaultProfileFlowHost.swift │ │ │ │ │ ├── ProfileFlowFactory.swift │ │ │ │ │ └── ProfileFlowHost+ProfileFlowController.swift │ │ │ └── Onboarding │ │ │ │ ├── DefaultOnboardingFlowHost.swift │ │ │ │ ├── Onboarding │ │ │ │ ├── OnboardingView.swift │ │ │ │ ├── OnboardingViewController.swift │ │ │ │ └── OnboardingViewModel.swift │ │ │ │ ├── OnboardingFlowFactory.swift │ │ │ │ └── OnboardingFlowHost+OnboardingFlowController.swift │ │ ├── PrimarySceneFlowFactory.swift │ │ └── PrimarySceneFlowHost+PrimarySceneFlowController.swift │ │ └── SceneDelegate.swift └── README.md ├── FlowViewPattern ├── FlowViewPattern.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── FlowViewPattern.xcscheme ├── FlowViewPattern │ ├── App │ │ ├── AppDelegate.swift │ │ ├── AppDependencies.swift │ │ ├── AppPath.swift │ │ ├── DefaultAppDependencies.swift │ │ ├── DefaultAppFlowViewFactory.swift │ │ ├── Extractor.swift │ │ └── FlowViewPatternApp.swift │ ├── Common │ │ └── Repositories │ │ │ └── Defaults │ │ │ ├── DefaultsRepository.swift │ │ │ └── UserDefaultsDefaultsRepository.swift │ ├── Content │ │ ├── AppFlowCoordinator.swift │ │ ├── AppFlowView.swift │ │ ├── AppFlowViewFactory.swift │ │ ├── AppFlowViewModel.swift │ │ ├── Main │ │ │ ├── Activity │ │ │ │ ├── ActivityFlowCoordinator.swift │ │ │ │ ├── ActivityFlowView.swift │ │ │ │ └── ActivityFlowViewModel.swift │ │ │ ├── Booking │ │ │ │ ├── BookingFlowCoordinator.swift │ │ │ │ ├── BookingFlowView.swift │ │ │ │ └── BookingFlowViewModel.swift │ │ │ ├── Explore │ │ │ │ ├── ExploreFlowCoordinator.swift │ │ │ │ ├── ExploreFlowView.swift │ │ │ │ ├── ExploreFlowViewFactory.swift │ │ │ │ ├── ExploreFlowViewModel.swift │ │ │ │ ├── MapAndList │ │ │ │ │ ├── List │ │ │ │ │ │ ├── ExploreListView.swift │ │ │ │ │ │ └── ExploreListViewModel.swift │ │ │ │ │ ├── Map │ │ │ │ │ │ ├── ExploreMapView.swift │ │ │ │ │ │ └── ExploreMapViewModel.swift │ │ │ │ │ ├── MapAndListFlowCoordinator.swift │ │ │ │ │ ├── MapAndListFlowView.swift │ │ │ │ │ ├── MapAndListFlowViewFactory.swift │ │ │ │ │ └── MapAndListFlowViewModel.swift │ │ │ │ └── News │ │ │ │ │ └── ExploreNewsView.swift │ │ │ ├── Greeting │ │ │ │ ├── WelcomeBackView.swift │ │ │ │ └── WelcomeBackViewModel.swift │ │ │ ├── MainFlowCoordinator.swift │ │ │ ├── MainFlowView.swift │ │ │ ├── MainFlowViewFactory.swift │ │ │ ├── MainFlowViewModel.swift │ │ │ └── Profile │ │ │ │ ├── ProfileFlowView.swift │ │ │ │ └── ProfileFlowViewModel.swift │ │ └── Onboarding │ │ │ ├── GetStarted │ │ │ ├── GetStartedView.swift │ │ │ └── GetStartedViewModel.swift │ │ │ ├── OnboardingFlowCoordinator.swift │ │ │ ├── OnboardingFlowView.swift │ │ │ ├── OnboardingFlowViewFactory.swift │ │ │ ├── OnboardingFlowViewModel.swift │ │ │ └── Welcome │ │ │ └── WelcomeView.swift │ ├── FlowViewPattern.entitlements │ ├── Info.plist │ └── Resources │ │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Mocks │ │ └── MockFlowCoordinator.swift │ │ └── PreviewContent │ │ ├── PreviewAppDependencies.swift │ │ ├── PreviewAssets.xcassets │ │ └── Contents.json │ │ ├── PreviewFlowCoordinator.swift │ │ └── PreviewFlowViewFactory.swift └── README.md ├── FullScreenImageTransition ├── FullScreenImageTransition.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved ├── FullScreenImageTransition │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── FullScreenImageViewController.swift │ ├── FullScreenTransitionManager.swift │ ├── Info.plist │ ├── Resources │ │ └── octocats │ │ │ ├── filmtocat.png │ │ │ ├── goretocat.png │ │ │ ├── jetpacktocat.png │ │ │ ├── manufacturetocat.png │ │ │ ├── murakamicat.png │ │ │ ├── skatetocat.png │ │ │ ├── spidertocat.png │ │ │ ├── stormtroopocat.png │ │ │ ├── swagtocat.png │ │ │ ├── waldocat.png │ │ │ └── welcometocat.png │ ├── SceneDelegate.swift │ ├── TableViewCell.swift │ └── TableViewController.swift └── README.md ├── GRPCFTW ├── GRPCFTWClient │ ├── GRPCFTWClient.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ ├── GRPCFTWClient │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Authentication │ │ │ └── AuthenticationService.swift │ │ ├── Base.lproj │ │ │ └── LaunchScreen.storyboard │ │ ├── Info.plist │ │ ├── Networking │ │ │ ├── ClientFactory.swift │ │ │ ├── GRPCClient+makeStreamingCallWithRetry.swift │ │ │ ├── GRPCClient+makeUnaryCallWithRetry.swift │ │ │ ├── Interceptors │ │ │ │ ├── AuthToken │ │ │ │ │ └── AuthTokenInterceptor.swift │ │ │ │ ├── FooServiceClientInterceptorFactory.swift │ │ │ │ └── Logging │ │ │ │ │ └── LoggingInterceptor.swift │ │ │ └── Models │ │ │ │ └── Generated │ │ │ │ ├── bar.grpc.swift │ │ │ │ ├── bar.pb.swift │ │ │ │ ├── foo.grpc.swift │ │ │ │ └── foo.pb.swift │ │ ├── SceneDelegate.swift │ │ ├── Services │ │ │ └── FooService.swift │ │ └── ViewController.swift │ └── README.md ├── GRPCFTWProtofiles │ ├── bar.proto │ └── foo.proto ├── GRPCFTWServer │ ├── GRPCFTWServer.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ ├── GRPCFTWServer │ │ ├── Networking │ │ │ ├── DefaultBarServiceProvider.swift │ │ │ ├── DefaultFooServiceProvider.swift │ │ │ ├── Interceptors │ │ │ │ ├── BarServiceServerInterceptorFactory.swift │ │ │ │ └── Logging │ │ │ │ │ └── LoggingInterceptor.swift │ │ │ └── Models │ │ │ │ └── Generated │ │ │ │ ├── bar.grpc.swift │ │ │ │ ├── bar.pb.swift │ │ │ │ ├── foo.grpc.swift │ │ │ │ └── foo.pb.swift │ │ └── main.swift │ └── README.md ├── README.md ├── proto-generate-client.sh └── proto-generate-server.sh ├── HTTPAPIProblem ├── HTTPAPIProblem.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── HTTPAPIProblem │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── HTTPAPIProblem.swift │ ├── HTTPAPIProblemApp.swift │ ├── OpaqueValue.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json ├── HTTPAPIProblemTests │ └── HTTPAPIProblemTests.swift └── README.md ├── HTTPClient ├── HTTPClient.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ └── xcshareddata │ │ └── xcschemes │ │ └── HTTPClient.xcscheme ├── HTTPClient │ ├── App │ │ ├── ContentView.swift │ │ ├── HTTPClientApp.swift │ │ └── ItemView.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Misc │ │ ├── PrintHTTPClientInterceptor.swift │ │ └── URLRequest+curlRepresentation.swift │ ├── Model │ │ ├── ErrorBody.swift │ │ └── Item.swift │ ├── Networking │ │ ├── DefaultHTTPClient.swift │ │ ├── HTTPClient.swift │ │ ├── HTTPClientError.swift │ │ ├── HTTPClientInterceptor.swift │ │ ├── HTTPMethod.swift │ │ └── HTTPMimeType.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json ├── HTTPServer │ ├── .gitignore │ ├── Package.resolved │ ├── Package.swift │ └── Sources │ │ └── HTTPServer │ │ ├── configure.swift │ │ ├── entrypoint.swift │ │ └── routes.swift └── README.md ├── ImprovedContainerViewController ├── ImprovedContainerViewController.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ImprovedContainerViewController │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ ├── SegmentedPageController │ │ └── SegmentedPageController.swift │ ├── SinglePageController │ │ └── SinglePageController.swift │ ├── TabBarController.swift │ └── ViewController.swift └── README.md ├── InteractiveAnimations ├── InteractiveAnimations.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── InteractiveAnimations │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── BottomSheetAnimationViewController.swift │ ├── BouncyCubeViewController.swift │ ├── Info.plist │ ├── RootViewController.swift │ └── SceneDelegate.swift └── README.md ├── KeyboardAvoidance ├── KeyboardAvoidance.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── KeyboardAvoidance │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── FormView.swift │ ├── Info.plist │ ├── KeyboardAvoidanceViewController.swift │ ├── LongFormViewController.swift │ ├── MediumFormViewController.swift │ ├── RootViewController.swift │ ├── SceneDelegate.swift │ └── ShortFormViewController.swift └── README.md ├── KeychainStorage ├── KeychainStorage.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── KeychainStorage │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── ContentViewModel.swift │ ├── KeychainStorageApp.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ └── SecureStorage │ │ ├── KeychainSecureStorage.swift │ │ └── SecureStorage.swift └── README.md ├── LICENSE ├── LiveMockData ├── LiveMockData.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── LiveMockData │ ├── AppDelegate.swift │ ├── EmojiCollectionViewCell.swift │ ├── EmojiRepository │ │ ├── EmojiRepository.swift │ │ └── MockEmojiRepository.swift │ ├── EmojisViewController.swift │ ├── Info.plist │ ├── MockData │ │ └── emojis.json │ ├── Resources │ │ ├── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ └── Base.lproj │ │ │ └── LaunchScreen.storyboard │ └── SceneDelegate.swift └── README.md ├── NetworkMonitoring ├── NetworkMonitoring.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── NetworkMonitoring │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── ContentViewModel.swift │ ├── NetworkMonitor.swift │ ├── NetworkMonitoringApp.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json └── README.md ├── OpaqueValue ├── OpaqueValue.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── OpaqueValue │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── OpaqueValue.swift │ ├── OpaqueValueApp.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json ├── OpaqueValueTests │ └── OpaqueValueTests.swift └── README.md ├── README.md ├── ResourceCache ├── README.md ├── ResourceCache.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ └── xcshareddata │ │ └── xcschemes │ │ └── ResourceCache.xcscheme ├── ResourceCache.xctestplan ├── ResourceCache │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── ResourceCache │ │ ├── CancelableResourceCache.swift │ │ └── ResourceCache.swift │ ├── ResourceCacheApp.swift │ └── Utils │ │ ├── AtomicCount.swift │ │ ├── LockedCount.swift │ │ ├── PendingOperation.swift │ │ ├── PendingValue.swift │ │ └── WaitingContinuationsLocker.swift └── ResourceCacheTests │ ├── CancelableResourceCacheTests.swift │ ├── PendingOperationTests.swift │ ├── PendingValueTests.swift │ └── ResourceCacheTests.swift ├── SharedAppAuthState ├── README.md ├── SharedAppAuthState.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── swiftpm │ │ │ └── Package.resolved │ └── xcshareddata │ │ └── xcschemes │ │ ├── SharedAppAuthState.xcscheme │ │ ├── SharedAppAuthStateAppClip.xcscheme │ │ ├── SharedAppAuthStateSecondApp.xcscheme │ │ └── SharedAppAuthStateWidgetExtension.xcscheme ├── SharedAppAuthState │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 128.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 16.png │ │ │ ├── 167.png │ │ │ ├── 172.png │ │ │ ├── 180.png │ │ │ ├── 196.png │ │ │ ├── 20.png │ │ │ ├── 216.png │ │ │ ├── 256.png │ │ │ ├── 29.png │ │ │ ├── 32.png │ │ │ ├── 40.png │ │ │ ├── 48.png │ │ │ ├── 50.png │ │ │ ├── 512.png │ │ │ ├── 55.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 64.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ ├── 88.png │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Auth │ │ ├── AuthError.swift │ │ ├── AuthService │ │ │ ├── Auth0AuthService.swift │ │ │ └── AuthService.swift │ │ ├── AuthStateRepository │ │ │ ├── AuthStateRepository.swift │ │ │ ├── KeychainAuthStateRepository.swift │ │ │ └── SharedUserDefaultsAuthStateRepository.swift │ │ └── AuthTokenProvider.swift │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ ├── SharedAppAuthState.entitlements │ └── ViewController.swift ├── SharedAppAuthStateAppClip │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 128.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 16.png │ │ │ ├── 167.png │ │ │ ├── 172.png │ │ │ ├── 180.png │ │ │ ├── 196.png │ │ │ ├── 20.png │ │ │ ├── 216.png │ │ │ ├── 256.png │ │ │ ├── 29.png │ │ │ ├── 32.png │ │ │ ├── 40.png │ │ │ ├── 48.png │ │ │ ├── 50.png │ │ │ ├── 512.png │ │ │ ├── 55.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 64.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ ├── 88.png │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── Info.plist │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── SharedAppAuthStateAppClip.entitlements │ └── SharedAppAuthStateAppClipApp.swift ├── SharedAppAuthStateSecondApp │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 128.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 16.png │ │ │ ├── 167.png │ │ │ ├── 172.png │ │ │ ├── 180.png │ │ │ ├── 196.png │ │ │ ├── 20.png │ │ │ ├── 216.png │ │ │ ├── 256.png │ │ │ ├── 29.png │ │ │ ├── 32.png │ │ │ ├── 40.png │ │ │ ├── 48.png │ │ │ ├── 50.png │ │ │ ├── 512.png │ │ │ ├── 55.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 64.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ ├── 88.png │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Auth │ │ ├── AuthError.swift │ │ ├── AuthService │ │ │ ├── Auth0AuthService.swift │ │ │ └── AuthService.swift │ │ ├── AuthStateRepository │ │ │ ├── AuthStateRepository.swift │ │ │ └── KeychainAuthStateRepository.swift │ │ └── AuthTokenProvider.swift │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ ├── SharedAppAuthStateSecondApp.entitlements │ └── ViewController.swift ├── SharedAppAuthStateWidget │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 128.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 16.png │ │ │ ├── 167.png │ │ │ ├── 172.png │ │ │ ├── 180.png │ │ │ ├── 196.png │ │ │ ├── 20.png │ │ │ ├── 216.png │ │ │ ├── 256.png │ │ │ ├── 29.png │ │ │ ├── 32.png │ │ │ ├── 40.png │ │ │ ├── 48.png │ │ │ ├── 50.png │ │ │ ├── 512.png │ │ │ ├── 55.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 64.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ ├── 88.png │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── WidgetBackground.colorset │ │ │ └── Contents.json │ ├── Auth │ │ └── WidgetAuthTokenProvider.swift │ ├── Info.plist │ ├── SharedAppAuthStateWidget.intentdefinition │ └── SharedAppAuthStateWidget.swift └── SharedAppAuthStateWidgetExtension.entitlements ├── SignalingStorage ├── README.md ├── SignalingStorage.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── SignalingStorage │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── ContentView.swift │ ├── Defaults │ ├── DefaultsStorage.swift │ ├── ObservableDefaults.swift │ └── SignalingDefaults.swift │ ├── Keychain │ ├── KeychainStorage.swift │ ├── ObservableKeychain.swift │ └── SignalingKeychain.swift │ ├── ObservableDefaultsView.swift │ ├── ObservableKeychainView.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── SignalingDefaultsView.swift │ ├── SignalingKeychainView.swift │ └── SignalingStorageApp.swift ├── StretchyTableViewHeader ├── README.md ├── StretchyTableViewHeader.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved └── StretchyTableViewHeader │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── octocats.imageset │ │ ├── Contents.json │ │ └── octocats.jpeg │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── FullScreenImageViewController.swift │ ├── FullScreenTransitionManager.swift │ ├── Info.plist │ ├── OctocatTableHeaderView.swift │ ├── Resources │ └── octocats │ │ ├── filmtocat.png │ │ ├── goretocat.png │ │ ├── jetpacktocat.png │ │ ├── manufacturetocat.png │ │ ├── murakamicat.png │ │ ├── skatetocat.png │ │ ├── spidertocat.png │ │ ├── stormtroopocat.png │ │ ├── swagtocat.png │ │ ├── waldocat.png │ │ └── welcometocat.png │ ├── SceneDelegate.swift │ ├── StretchyTableHeaderView.swift │ ├── TableViewCell.swift │ └── TableViewController.swift ├── SwiftUIHTML ├── README.md ├── SwiftUIHTML.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── SwiftUIHTML │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── AttributedText.swift │ ├── ContentView.swift │ ├── EnvironmentValues+theme.swift │ ├── NSAttributedString+html.swift │ ├── NSAttributedString+themedHtml.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── SwiftUIHTMLApp.swift │ └── UIColor+hex.swift ├── VerticalSlices ├── README.md ├── VerticalSlices.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── swiftpm │ │ └── Package.resolved └── VerticalSlices │ ├── App │ └── VerticalSlicesApp.swift │ ├── Common │ ├── CryptographicKeyStorage.swift │ ├── DefaultsStorage.swift │ ├── EnvironmentValues+DatabaseClient.swift │ ├── EnvironmentValues+HTTPClient.swift │ ├── FeatureToggles.swift │ └── SecureStorage.swift │ ├── Domain │ └── DomainModels.swift │ ├── Features │ ├── Explore │ │ └── ExploreView.swift │ ├── Home │ │ ├── HomeModels.swift │ │ ├── HomeView.swift │ │ └── Profile │ │ │ └── ProfileView.swift │ ├── Login │ │ └── LoginView.swift │ ├── More │ │ └── MoreView.swift │ └── RootView.swift │ └── Resources │ └── Assets.xcassets │ ├── AccentColor.colorset │ └── Contents.json │ ├── AppIcon.appiconset │ └── Contents.json │ └── Contents.json ├── ViewModelHierarchy ├── README.md ├── ViewModelHierarchy.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── ViewModelHierarchy │ ├── Actionable.swift │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── CardFlipTransition.swift │ ├── Feature │ ├── About │ │ └── AboutCoordinatorView.swift │ ├── Main │ │ ├── Enrollment │ │ │ └── EnrollmentCoordinatorView.swift │ │ ├── Home │ │ │ ├── Enroll │ │ │ │ └── EnrollView.swift │ │ │ ├── Home │ │ │ │ └── HomeView.swift │ │ │ ├── HomeCoordinatorView.swift │ │ │ └── Profile │ │ │ │ └── ProfileView.swift │ │ ├── MainCoordinatorView.swift │ │ ├── More │ │ │ ├── Details │ │ │ │ └── DetailsView.swift │ │ │ ├── More │ │ │ │ └── MoreView.swift │ │ │ └── MoreCoordinatorView.swift │ │ └── Settings │ │ │ └── SettingsCoordinatorView.swift │ └── Onboarding │ │ └── OnboardingCoordinatorView.swift │ ├── Hashable+extensions.swift │ ├── Info.plist │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── RootCoordinatorView.swift │ ├── ViewModelHierarchy.entitlements │ └── ViewModelHierarchyApp.swift └── WebSocketClient ├── README.md ├── WebSocketClient.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ └── swiftpm │ └── Package.resolved ├── WebSocketClient ├── App │ ├── ContentView.swift │ ├── ItemView.swift │ └── WebSocketClientApp.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Model │ ├── IncomingMessage.swift │ ├── Item.swift │ └── OutgoingMessage.swift ├── Networking │ ├── WebSocketConnection.swift │ └── WebSocketConnectionFactory.swift └── Preview Content │ └── Preview Assets.xcassets │ └── Contents.json └── WebSocketServer ├── .gitignore ├── Package.resolved ├── Package.swift └── Sources └── WebSocketServer ├── configure.swift ├── entrypoint.swift └── routes.swift /ActionableViewModel/ActionableViewModel.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/ActionableViewModelApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionableViewModelApp.swift 3 | // ActionableViewModel 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/06/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ActionableViewModelApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ActionableViewModel 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/06/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | RootCoordinatorView( 13 | viewModel: RootCoordinatorView.ViewModel { _ in } 14 | ) 15 | } 16 | } 17 | 18 | #Preview { 19 | ContentView() 20 | } 21 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/Feature/Main/Home/Profile/ProfileView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileView.swift 3 | // ActionableViewModel 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/06/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ProfileView: View { 11 | var body: some View { 12 | ScrollView { 13 | Text("Profile name") 14 | .padding() 15 | 16 | Text("Profile details") 17 | .padding() 18 | } 19 | .navigationTitle("Profile") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/Feature/Main/More/Details/DetailsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailsView.swift 3 | // ActionableViewModel 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/06/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct DetailsView: View { 11 | var body: some View { 12 | ScrollView { 13 | Text("Details") 14 | .padding() 15 | } 16 | .navigationTitle("Details") 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ActionableViewModel/ActionableViewModel/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // AlternateAppIcon 4 | // 5 | // Created by Thomas Asheim Smedmann on 25/06/2023. 6 | // 7 | 8 | import UIKit 9 | 10 | final class AppDelegate: NSObject, UIApplicationDelegate { 11 | 12 | private(set) lazy var dependencies = DefaultDependencies() 13 | 14 | func application( 15 | _ application: UIApplication, 16 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil 17 | ) -> Bool { 18 | 19 | return true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Application.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Application.swift 3 | // AlternateAppIcon 4 | // 5 | // Created by Thomas Asheim Smedmann on 25/06/2023. 6 | // 7 | 8 | import UIKit 9 | 10 | protocol Application: AnyObject { 11 | var alternateIconName: String? { get } 12 | func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Void)?) 13 | } 14 | 15 | extension UIApplication: Application {} 16 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Blue Green.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon BlueGreen.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Blue Green.appiconset/Icon BlueGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Blue Green.appiconset/Icon BlueGreen.png -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Blue Red.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon BlueRed.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Blue Red.appiconset/Icon BlueRed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Blue Red.appiconset/Icon BlueRed.png -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Green Red.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon GreenRed.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Green Red.appiconset/Icon GreenRed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Green Red.appiconset/Icon GreenRed.png -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Red Blue.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon RedBlue.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Red Blue.appiconset/Icon RedBlue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/AlternateAppIcon/AlternateAppIcon/Assets.xcassets/Red Blue.appiconset/Icon RedBlue.png -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Preview Content/MockAppInfoProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MockAppInfoProvider.swift 3 | // AlternateAppIcon 4 | // 5 | // Created by Thomas Asheim Smedmann on 25/06/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | final class MockAppInfoProvider: AppInfoProvider { 11 | var bundleName: String = "" 12 | var bundleDisplayName: String = "" 13 | var bundleIdentifier: String = "" 14 | var bundleShortVersionString: String = "" 15 | var bundleVersion: String = "" 16 | var primaryAppIconName: String = "" 17 | var alternateAppIconNames: [String] = [] 18 | } 19 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Preview Content/MockApplication.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MockApplication.swift 3 | // AlternateAppIcon 4 | // 5 | // Created by Thomas Asheim Smedmann on 25/06/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | final class MockApplication: Application { 11 | var alternateIconName: String? = nil 12 | 13 | func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Void)?) { 14 | completionHandler?(nil) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Preview Content/MockDependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MockDependencies.swift 3 | // AlternateAppIcon 4 | // 5 | // Created by Thomas Asheim Smedmann on 25/06/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | final class MockDependencies: Dependencies { 11 | let application: Application = MockApplication() 12 | let appInfoProvider: AppInfoProvider = MockAppInfoProvider() 13 | 14 | private init() {} 15 | } 16 | 17 | extension MockDependencies { 18 | static let shared = MockDependencies() 19 | } 20 | -------------------------------------------------------------------------------- /AlternateAppIcon/AlternateAppIcon/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AlternateAppIcon/README.md: -------------------------------------------------------------------------------- 1 | # Dynamically alternate/change app icon 2 | 3 | A simple example (in SwiftUI) on how to dynamically change the App Icon of you app. Perfect if you want to give your users a little extra when it come to personalisation of your app! 4 | -------------------------------------------------------------------------------- /BLEChat/BLEChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BLEChat/BLEChat.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BLEChat/BLEChat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "TinyConstraints", 6 | "repositoryURL": "git@github.com:roberthein/TinyConstraints.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "3262e5c591d4ab6272255df2087a01bbebd138dc", 10 | "version": "4.0.2" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /BLEChat/BLEChat/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /BLEChat/BLEChat/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BLEChat/BLEChat/Bluetooth/BluetoothError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BluetoothError.swift 3 | // BLEChat 4 | // 5 | // Created by Thomas Asheim Smedmann on 18/01/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | enum BluetoothError: Error { 11 | case invalidState 12 | case unknownPeripheral 13 | case connectionFailure 14 | } 15 | -------------------------------------------------------------------------------- /BLEChat/BLEChat/Dependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dependencies.swift 3 | // BLEChat 4 | // 5 | // Created by Thomas Asheim Smedmann on 14/01/2022. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | enum Dependencies { 12 | static let chatHostScanner: ChatHostScanner = CoreBluetoothChatHostScanner() 13 | static let chatHost: ChatHost = CoreBluetoothChatHost(chatBroadcastingName: UIDevice.current.name) 14 | } 15 | -------------------------------------------------------------------------------- /BLEChat/BLEChat/Features/Shared/ChatSection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChatSection.swift 3 | // BLEChat 4 | // 5 | // Created by Thomas Asheim Smedmann on 17/04/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | struct ChatSection { 11 | let title: String 12 | var messages: [ChatBubbleMessage] 13 | } 14 | -------------------------------------------------------------------------------- /BackgroundCleanup/BackgroundCleanup.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BackgroundCleanup/BackgroundCleanup.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BackgroundCleanup/BackgroundCleanup/App/AppDependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDependencies.swift 3 | // BackgroundCleanup 4 | // 5 | // Created by Thomas Asheim Smedmann on 17/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AppDependencies: AnyObject { 11 | var application: Application { get } 12 | var itemRepository: ItemRepository { get } 13 | var refreshService: RefreshService { get } 14 | var cleanupService: CleanupService { get } 15 | } 16 | -------------------------------------------------------------------------------- /BackgroundCleanup/BackgroundCleanup/App/UIApplication+Application.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Application.swift 3 | // BackgroundCleanup 4 | // 5 | // Created by Thomas Asheim Smedmann on 17/07/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | protocol Application: AnyObject { 11 | func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier 12 | func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier) 13 | } 14 | 15 | extension UIApplication: Application { } 16 | -------------------------------------------------------------------------------- /BackgroundCleanup/BackgroundCleanup/Common/Models/Item.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Item.swift 3 | // BackgroundCleanup 4 | // 5 | // Created by Thomas Asheim Smedmann on 16/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Item: Codable { 11 | let text: String 12 | let timestamp: Date 13 | } 14 | -------------------------------------------------------------------------------- /BackgroundCleanup/BackgroundCleanup/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /BackgroundCleanup/BackgroundCleanup/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BottomSheetController/BottomSheetController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BottomSheetController/BottomSheetController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BottomSheetController/BottomSheetController/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /BottomSheetController/BottomSheetController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BottomSheetController/README.md: -------------------------------------------------------------------------------- 1 | # Dynamic sized bottom sheet controller 2 | 3 | Check out [Custom dynamic sized bottom sheet (iOS)](https://medium.com/@thomsmed/custom-dynamic-sized-bottom-sheet-ios-fbae44485255)! 4 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Flavours/Develop/ConstantsDevelop.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // BuildConfigurations 4 | // 5 | // Created by Thomas Asheim Smedmann on 04/11/2022. 6 | // 7 | #if FLAVOUR_DEVELOP 8 | import Foundation 9 | 10 | enum Constants { 11 | static let hello = "Hello from the Develop flavour" 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Flavours/Develop/Properties.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SomeProperty 6 | Some property value for Develop 7 | 8 | 9 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Flavours/Prod/ConstantsProd.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // BuildConfigurations 4 | // 5 | // Created by Thomas Asheim Smedmann on 04/11/2022. 6 | // 7 | #if FLAVOUR_PROD 8 | import Foundation 9 | 10 | enum Constants { 11 | static let hello = "Hello from the Prod flavour" 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Flavours/Prod/Properties.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SomeProperty 6 | Some property value for Prod 7 | 8 | 9 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Flavours/Properties.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SomeProperty 6 | Some property value for Develop 7 | 8 | 9 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Flavours/Test/ConstantsTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constant.swift 3 | // BuildConfigurations 4 | // 5 | // Created by Thomas Asheim Smedmann on 04/11/2022. 6 | // 7 | #if FLAVOUR_TEST 8 | import Foundation 9 | 10 | enum Constants { 11 | static let hello = "Hello from the Test flavour" 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Flavours/Test/Properties.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SomeProperty 6 | Some property value for Test 7 | 8 | 9 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /BuildConfigurations/BuildConfigurations/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps/ConsecutiveTabTapsApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConsecutiveTabTapsApp.swift 3 | // ConsecutiveTabTaps 4 | // 5 | // Created by Thomas Asheim Smedmann on 27/08/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ConsecutiveTabTapsApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | MainView(viewModel: MainViewModel()) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps/Countries/Country.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Country.swift 3 | // ConsecutiveTabTaps 4 | // 5 | // Created by Thomas Asheim Smedmann on 27/08/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Country: Identifiable, Hashable { 11 | var id: String 12 | let emojiFlag: String? 13 | } 14 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/ConsecutiveTabTaps/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ConsecutiveTabTaps/README.md: -------------------------------------------------------------------------------- 1 | # Handle consecutive taps on a tab in a TabView 2 | 3 | An example on how to utilise consecutive taps on a tab in a TabView. Consecutive taps on the same tab will make a NavigationStack pop to its root View, and a ScrollView scroll to its first item. 4 | -------------------------------------------------------------------------------- /ContainerViewController/ContainerViewController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ContainerViewController/ContainerViewController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ContainerViewController/ContainerViewController.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "Cartography", 6 | "repositoryURL": "https://github.com/robb/Cartography", 7 | "state": { 8 | "branch": null, 9 | "revision": "b75197ea134f42b5feafb04b526b37eb1a41034b", 10 | "version": "4.0.0" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /ContainerViewController/ContainerViewController/App/AppDependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDependencies.swift 3 | // ContainerViewController 4 | // 5 | // Created by Thomas Asheim Smedmann on 02/04/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AppDependencies { 11 | // Dependencies goes here 12 | } 13 | 14 | final class DefaultAppDependencies { 15 | 16 | init() { 17 | // Do some initialisation 18 | } 19 | } 20 | 21 | extension DefaultAppDependencies: AppDependencies { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ContainerViewController/ContainerViewController/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ContainerViewController/ContainerViewController/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ContainerViewController/README.md: -------------------------------------------------------------------------------- 1 | # Custom Container View Controller 2 | 3 | Check out [Swap root view controllers using a custom container view controller](https://medium.com/@thomsmed/swap-root-view-controllers-using-a-custom-container-view-controller-fae93f5ad2c0)! 4 | -------------------------------------------------------------------------------- /CustomInterfaceBuilderView/CustomInterfaceBuilderView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomInterfaceBuilderView/CustomInterfaceBuilderView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CustomInterfaceBuilderView/CustomInterfaceBuilderView/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CustomInterfaceBuilderView/CustomInterfaceBuilderView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CustomInterfaceBuilderView/CustomInterfaceBuilderView/CircularView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircleView.swift 3 | // CustomInterfaceBuilderView 4 | // 5 | // Created by Thomas Asheim Smedmann on 10/09/2021. 6 | // 7 | 8 | import UIKit 9 | 10 | @IBDesignable 11 | class CircularView: UIView { 12 | override func layoutSubviews() { 13 | super.layoutSubviews() 14 | layer.cornerRadius = CGFloat(min(bounds.width / 2, bounds.height / 2)) 15 | layer.masksToBounds = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CustomInterfaceBuilderView/README.md: -------------------------------------------------------------------------------- 1 | # Custom Interface Builder View 2 | 3 | A simple example to showcase the use of [@IBDesignable and @IBInspectable](https://nshipster.com/ibinspectable-ibdesignable/) to build your own custom Interface Builder View. 4 | -------------------------------------------------------------------------------- /CustomPresentationController/CustomPresentationController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomPresentationController/CustomPresentationController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CustomPresentationController/CustomPresentationController/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CustomPresentationController/CustomPresentationController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CustomPresentationController/CustomPresentationController/Assets.xcassets/fruit.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "fruit.jpeg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /CustomPresentationController/CustomPresentationController/Assets.xcassets/fruit.imageset/fruit.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/CustomPresentationController/CustomPresentationController/Assets.xcassets/fruit.imageset/fruit.jpeg -------------------------------------------------------------------------------- /CustomPresentationController/README.md: -------------------------------------------------------------------------------- 1 | # Custom Presentation Controller 2 | 3 | A simple example on how to create your very own [UIPresentationController](https://developer.apple.com/documentation/uikit/uipresentationcontroller). 4 | -------------------------------------------------------------------------------- /DialogController/DialogController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DialogController/DialogController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DialogController/DialogController/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DialogController/DialogController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /DialogController/README.md: -------------------------------------------------------------------------------- 1 | # Dynamic sized dialog controller 2 | 3 | Check out [Custom dynamic sized dialog (iOS)](https://medium.com/@thomsmed/custom-dynamic-sized-dialog-ios-84a6e2a2774d)! 4 | -------------------------------------------------------------------------------- /DynamicAnimations/DynamicAnimations.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DynamicAnimations/DynamicAnimations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DynamicAnimations/DynamicAnimations/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DynamicAnimations/DynamicAnimations/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DynamicAnimations/DynamicAnimations/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /DynamicAnimations/README.md: -------------------------------------------------------------------------------- 1 | # Dynamic Animations with UIDynamicAnimator 2 | 3 | This sample app showcase how to use the awesome UIDynamicAnimator to drive dynamic and physics based animations. 4 | The UIDynamicAnimator has a variety of UIDynamicBehaviors that can be added and combined for various effects. A lot of the properties of these UIDynamicBehaviors can also be changed dynamically while the animator is running! 5 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "episode3.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode3.imageset/episode3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode3.imageset/episode3.png -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "episode4.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode4.imageset/episode4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode4.imageset/episode4.png -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "episode5.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode5.imageset/episode5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode5.imageset/episode5.png -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "episode6.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode6.imageset/episode6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode6.imageset/episode6.png -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "episode7.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode7.imageset/episode7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode7.imageset/episode7.png -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "episode8.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode8.imageset/episode8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode8.imageset/episode8.png -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "episode9.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode9.imageset/episode9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/episode9.imageset/episode9.png -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/luke.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "luke.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/luke.imageset/luke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/DynamicTableHeaderView/DynamicTableHeaderView/Assets.xcassets/luke.imageset/luke.png -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Feature/CommonError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CommonError.swift 3 | // ErrorResponder 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/09/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | public enum CommonError: Error { 11 | case networkTrouble 12 | case sessionExpired 13 | case blocked 14 | } 15 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Feature/FeatureOne/FeatureOneError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeatureOneError.swift 3 | // ErrorResponder 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/09/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum FeatureOneError: Error { 11 | case blocked 12 | case common(CommonError) 13 | } 14 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Feature/FeatureOne/PageOne/PageOneFeatureOneError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageOneFeatureOneError.swift 3 | // ErrorResponder 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/09/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum PageOneFeatureOneError: Error { 11 | case wrongInput 12 | case needsConfirmation 13 | case feature(FeatureOneError) 14 | case common(CommonError) 15 | } 16 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Feature/FeatureTwo/FeatureTwoError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeatureTwoError.swift 3 | // ErrorResponder 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/09/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum FeatureTwoError: Error { 11 | case blocked 12 | case common(CommonError) 13 | } 14 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Feature/FeatureTwo/PageOne/PageOneFeatureTwoError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageOneFeatureTwoError.swift 3 | // ErrorResponder 4 | // 5 | // Created by Thomas Asheim Smedmann on 15/09/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum PageOneFeatureTwoError: Error { 11 | case wrongInput 12 | case needsConfirmation 13 | case feature(FeatureTwoError) 14 | case common(CommonError) 15 | } 16 | -------------------------------------------------------------------------------- /ErrorResponder/ErrorResponder/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ExpandableTableViewCell/ExpandableTableViewCell.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ExpandableTableViewCell/ExpandableTableViewCell.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ExpandableTableViewCell/ExpandableTableViewCell/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ExpandableTableViewCell/ExpandableTableViewCell/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ExpandableTableViewCell/ExpandableTableViewCell/ExpandableTableViewCellDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExpandableTableViewCellDelegate.swift 3 | // ExpandableTableViewCell 4 | // 5 | // Created by Thomas Asheim Smedmann on 05/08/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | protocol ExpandableTableViewCellDelegate: AnyObject { 11 | func expandableTableViewCell(_ tableViewCell: UITableViewCell, expanded: Bool) 12 | } 13 | -------------------------------------------------------------------------------- /ExtendedSplashScreen/ExtendedSplashScreen.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ExtendedSplashScreen/ExtendedSplashScreen.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ExtendedSplashScreen/ExtendedSplashScreen/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ExtendedSplashScreen/ExtendedSplashScreen/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ExtendedSplashScreen/ExtendedSplashScreen/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ExtendedSplashScreen/README.md: -------------------------------------------------------------------------------- 1 | # Extended Splash Screen on App startup 2 | 3 | Perfect when you need to do some initial checks before you can let the user start using the app. 4 | 5 | And definitely a better option than just blocking main thread on app start up. 6 | -------------------------------------------------------------------------------- /FeatureModules/CoreKit/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /FeatureModules/CoreKit/README.md: -------------------------------------------------------------------------------- 1 | # CoreKit 2 | 3 | Some package containing core features and utilities of the app. 4 | -------------------------------------------------------------------------------- /FeatureModules/CoreKit/Sources/CoreKit/Coordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Coordinator.swift 3 | // 4 | // 5 | // Created by Thomas Asheim Smedmann on 20/11/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | public protocol Coordinator: AnyObject { 11 | var navigationController: UINavigationController { get set } 12 | var childCoordinators: [Coordinator] { get set } 13 | 14 | func start() 15 | } 16 | 17 | public extension Coordinator { 18 | func removeChildCoordinator(_ coordinator: Coordinator) { 19 | childCoordinators.removeAll(where: { $0 === coordinator }) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FeatureModules/FeatureModules.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FeatureModules/FeatureModules.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FeatureModules/FeatureModules/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FeatureModules/FeatureModules/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /FeatureModules/FeatureModules/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FeatureModules/FeatureOneKit/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /FeatureModules/FeatureOneKit/README.md: -------------------------------------------------------------------------------- 1 | # FeatureOneKit 2 | 3 | Some package containing everything related to Feature One. The feature is exposed via a selected protocols and types - like a root Coordinator implementation, a CoordinatorDelegate protocol and configuration structs. 4 | -------------------------------------------------------------------------------- /FeatureModules/FeatureThreeKit/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /FeatureModules/FeatureThreeKit/README.md: -------------------------------------------------------------------------------- 1 | # FeatureThreeKit 2 | 3 | Some package containing everything related to Feature Three. The feature is exposed via a selected protocols and types - like a root Coordinator implementation, a CoordinatorDelegate protocol and configuration structs. 4 | -------------------------------------------------------------------------------- /FeatureModules/FeatureThreeKit/Sources/FeatureThreeKit/CustomNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomNavigationController.swift 3 | // 4 | // 5 | // Created by Thomas Asheim Smedmann on 04/04/2023. 6 | // 7 | 8 | import UIKit 9 | 10 | final class CustomNavigationController: UINavigationController { 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | 15 | // Customize the custom UINavigationController 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /FeatureModules/FeatureTwoKit/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /FeatureModules/FeatureTwoKit/README.md: -------------------------------------------------------------------------------- 1 | # FeatureTwoKit 2 | 3 | Some package containing everything related to Feature Two. The feature is exposed via a selected protocols and types - like a root Coordinator implementation, a CoordinatorDelegate protocol and configuration structs. 4 | -------------------------------------------------------------------------------- /FeatureModules/README.md: -------------------------------------------------------------------------------- 1 | # Multi Module App 2 | 3 | An example on how to spread app features into multiple feature modules (Swift Packages). 4 | 5 | The Coordinator pattern is used as a navigation pattern and a way to separate responsibility (and features). 6 | Each feature module's entry point is a feature specific root Coordinator implementation. Feature "notifications"/"events" (e.g. when the feature has completed normal flow) are exposed via a CoordinatorDelegate. 7 | -------------------------------------------------------------------------------- /FlowControllerPattern/ExamplePush.apns: -------------------------------------------------------------------------------- 1 | { 2 | "aps": { 3 | "alert" : { 4 | "title" : "Test Notification", 5 | "subtitle" : "Just a test notification", 6 | "body" : "This notification was sent to you for testing purpose" 7 | }, 8 | "sound": "default", 9 | "badge": 1, 10 | "category" : "LINK" 11 | }, 12 | "link": "https://www.flowcontrolpattern.com//app/primary/main/explore/store/map/1a2b/booking/checkout?service=123&product=123" 13 | } 14 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/App/AppDependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDependencies.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 04/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AppDependencies: AnyObject { 11 | var analytics: AnalyticsLogger { get } 12 | var crashlytics: CrashlyticsRecorder { get } 13 | var storeService: StoreService { get } 14 | var bookingService: BookingService { get } 15 | } 16 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/App/AppFlowFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppFlowFactory.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 13/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AppFlowFactory: AnyObject { 11 | func makePrimarySceneFlowHost(with flowController: AppFlowController) -> PrimarySceneFlowHost 12 | } 13 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/App/FlowControllerPattern.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Models/ShoppingCart/ShoppingCart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShoppingCart.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class ShoppingCart { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Models/Store/Store.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Store.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 07/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | struct StoreInfo: Equatable { 11 | let id: String 12 | let name: String 13 | } 14 | 15 | struct StoreDetails { 16 | let id: String 17 | let name: String 18 | let description: String 19 | } 20 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Services/Analytics/DefaultAnalyticsLogger.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultAnalyticsLogger.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class DefaultAnalyticsLogger { 11 | 12 | } 13 | 14 | extension DefaultAnalyticsLogger: AnalyticsLogger { 15 | 16 | func log(_ event: Analytics.Event) { 17 | 18 | } 19 | 20 | func set(_ property: Analytics.Property) { 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Services/Booking/BookingService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookingService.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol BookingService: AnyObject { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Services/Booking/DefaultBookingService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultBookingService.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class DefaultBookingService { 11 | 12 | } 13 | 14 | extension DefaultBookingService: BookingService { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Services/Crashlytics/CrashlyticsRecorder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CrashlyticsRecorder.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | enum Crashlytics { 11 | enum Level { 12 | case info 13 | case warning 14 | case fatal 15 | } 16 | } 17 | 18 | protocol CrashlyticsRecorder { 19 | func record(_ error: Error, level: Crashlytics.Level) 20 | } 21 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Services/Crashlytics/DefaultCrashlyticsRecorder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultCrashlyticsRecorder.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class DefaultCrashlyticsRecorder { 11 | 12 | } 13 | 14 | extension DefaultCrashlyticsRecorder: CrashlyticsRecorder { 15 | 16 | func record(_ error: Error, level: Crashlytics.Level) { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Services/Store/DefaultStoreService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultStoreService.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class DefaultStoreService { 11 | 12 | } 13 | 14 | extension DefaultStoreService: StoreService { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Common/Services/Store/StoreService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoreService.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol StoreService: AnyObject { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Scenes/Primary/Features/Main/Activity/ActivityFlowFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivityFlowFactory.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 13/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol ActivityFlowFactory: AnyObject { 11 | 12 | } 13 | 14 | extension DefaultAppFlowFactory: ActivityFlowFactory { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Scenes/Primary/Features/Main/Activity/ActivityFlowHost+ActivityFlowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivityFlowHost+ActivityFlowController.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 06/07/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | protocol ActivityFlowController: AnyObject { 11 | 12 | } 13 | 14 | protocol ActivityFlowHost: ActivityFlowController & UIViewController { 15 | func start(_ page: AppPage.Primary.Main.Activity) 16 | func go(to page: AppPage.Primary.Main.Activity) 17 | } 18 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Scenes/Primary/Features/Main/Activity/Purchases/PurchasesFlowHost+PurchasesFlowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PurchasesFlowHost+PurchasesFlowController.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 06/07/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | protocol PurchasesFlowController: AnyObject { 11 | 12 | } 13 | 14 | protocol PurchasesFlowHost: PurchasesFlowController & UIViewController { 15 | func start(_ page: AppPage.Primary.Main.Activity.Purchases) 16 | func go(to page: AppPage.Primary.Main.Activity.Purchases) 17 | } 18 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Scenes/Primary/Features/Main/Explore/Referral/ReferralViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReferralViewController.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 06/07/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | protocol ReferralViewHolder: UIViewController { 11 | 12 | } 13 | 14 | final class ReferralViewController: UIViewController { 15 | 16 | } 17 | 18 | extension ReferralViewController: ReferralViewHolder { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Scenes/Primary/Features/Main/Explore/Store/StoreFlowModels.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoreFlowModels.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 13/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | enum StoreFlow { 11 | 12 | struct FilterOptions { 13 | let country: String 14 | let onlyOpen: Bool 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Scenes/Primary/Features/Main/Profile/ProfileFlowFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileFlowFactory.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 13/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol ProfileFlowFactory: AnyObject { 11 | 12 | } 13 | 14 | extension DefaultAppFlowFactory: ProfileFlowFactory { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /FlowControllerPattern/FlowControllerPattern/Scenes/Primary/Features/Main/Profile/ProfileFlowHost+ProfileFlowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileFlowHost+ProfileFlowController.swift 3 | // FlowControllerPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 06/07/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | protocol ProfileFlowController: AnyObject { 11 | 12 | } 13 | 14 | protocol ProfileFlowHost: ProfileFlowController & UIViewController { 15 | func start(_ page: AppPage.Primary.Main.Profile) 16 | func go(to page: AppPage.Primary.Main.Profile) 17 | } 18 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/App/AppDependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDependencies.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AppDependencies: AnyObject { 11 | var defaultsRepository: DefaultsRepository { get } 12 | } 13 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/App/DefaultAppDependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultAppDependencies.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class DefaultAppDependencies: AppDependencies { 11 | 12 | let defaultsRepository: DefaultsRepository 13 | 14 | init() { 15 | defaultsRepository = UserDefaultsDefaultsRepository() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/App/DefaultAppFlowViewFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultAppFlowViewFactory.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 12/08/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class DefaultAppFlowViewFactory { 11 | 12 | internal let appDependencies: AppDependencies 13 | 14 | init(appDependencies: AppDependencies) { 15 | self.appDependencies = appDependencies 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/AppFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | import Combine 10 | 11 | protocol AppFlowCoordinator: AnyObject { 12 | func onboardingCompleteContinueToMain() 13 | } 14 | 15 | extension PreviewFlowCoordinator: AppFlowCoordinator { 16 | func onboardingCompleteContinueToMain() {} 17 | } 18 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/Activity/ActivityFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivityFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol ActivityFlowCoordinator: AnyObject { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/Activity/ActivityFlowViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivityFlowViewModel.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class ActivityFlowViewModel: ObservableObject { 11 | 12 | func go(to path: AppPath.Main.Activity) { 13 | 14 | } 15 | } 16 | 17 | extension ActivityFlowViewModel: ActivityFlowCoordinator { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/Booking/BookingFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookingFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol BookingFlowCoordinator: AnyObject { 11 | 12 | } 13 | 14 | extension PreviewFlowCoordinator: BookingFlowCoordinator { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/Booking/BookingFlowViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookingFlowViewModel.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class BookingFlowViewModel: ObservableObject { 11 | 12 | } 13 | 14 | extension BookingFlowViewModel: BookingFlowCoordinator { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/Explore/ExploreFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExploreFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | import Combine 10 | 11 | protocol ExploreFlowCoordinator: AnyObject { 12 | func continueToNews() 13 | func continueToBooking() 14 | } 15 | 16 | extension PreviewFlowCoordinator: ExploreFlowCoordinator { 17 | func continueToNews() {} 18 | func continueToBooking() {} 19 | } 20 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/Explore/MapAndList/MapAndListFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapAndListFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 07/08/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol MapAndListFlowCoordinator: AnyObject { 11 | func showMap() 12 | func showList() 13 | func continueToNews() 14 | func continueToBooking() 15 | } 16 | 17 | extension PreviewFlowCoordinator: MapAndListFlowCoordinator { 18 | func showMap() {} 19 | func showList() {} 20 | } 21 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/Explore/News/ExploreNewsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExploreNewsView.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 07/08/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ExploreNewsView: View { 11 | var body: some View { 12 | Text("Explore news view") 13 | } 14 | } 15 | 16 | struct ExploreNewsView_Previews: PreviewProvider { 17 | static var previews: some View { 18 | ExploreNewsView() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Main/MainFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | import Combine 10 | 11 | protocol MainFlowCoordinator: AnyObject { 12 | func presentBooking() 13 | } 14 | 15 | extension PreviewFlowCoordinator: MainFlowCoordinator { 16 | func presentBooking() {} 17 | } 18 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Onboarding/OnboardingFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnboardingFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol OnboardingFlowCoordinator: AnyObject { 11 | func onboardingComplete() 12 | } 13 | 14 | extension PreviewFlowCoordinator: OnboardingFlowCoordinator { 15 | 16 | func onboardingComplete() { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Content/Onboarding/Welcome/WelcomeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WelcomeView.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 13/08/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct WelcomeView: View { 11 | 12 | var body: some View { 13 | VStack { 14 | Text("Welcome! 👋") 15 | } 16 | } 17 | } 18 | 19 | struct WelcomeView_Previews: PreviewProvider { 20 | static var previews: some View { 21 | WelcomeView() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/FlowViewPattern.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleURLTypes 6 | 7 | 8 | CFBundleTypeRole 9 | Viewer 10 | CFBundleURLName 11 | com.thomsmed.flowviewpattern 12 | CFBundleURLSchemes 13 | 14 | flowviewpattern 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Resources/Mocks/MockFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MockFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class PreviewFlowCoordinator { 11 | 12 | static let shared = PreviewFlowCoordinator() 13 | 14 | private init() {} 15 | } 16 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Resources/PreviewContent/PreviewAppDependencies.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreviewAppDependencies.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class PreviewAppDependencies: AppDependencies { 11 | 12 | static let shared: AppDependencies = PreviewAppDependencies() 13 | 14 | let defaultsRepository: DefaultsRepository 15 | 16 | private init() { 17 | defaultsRepository = UserDefaultsDefaultsRepository() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Resources/PreviewContent/PreviewAssets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Resources/PreviewContent/PreviewFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreviewFlowCoordinator.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 31/07/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | final class PreviewFlowCoordinator { 11 | 12 | static let shared = PreviewFlowCoordinator() 13 | 14 | private init() {} 15 | } 16 | -------------------------------------------------------------------------------- /FlowViewPattern/FlowViewPattern/Resources/PreviewContent/PreviewFlowViewFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreviewFlowViewFactory.swift 3 | // FlowViewPattern 4 | // 5 | // Created by Thomas Asheim Smedmann on 12/08/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | struct PreviewFlowViewFactory { 11 | 12 | private static let appDependencies = PreviewAppDependencies.shared 13 | 14 | static let shared = DefaultAppFlowViewFactory(appDependencies: appDependencies) 15 | 16 | private init() {} 17 | } 18 | -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "TinyConstraints", 6 | "repositoryURL": "git@github.com:roberthein/TinyConstraints.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "3262e5c591d4ab6272255df2087a01bbebd138dc", 10 | "version": "4.0.2" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/filmtocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/filmtocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/goretocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/goretocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/jetpacktocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/jetpacktocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/manufacturetocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/manufacturetocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/murakamicat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/murakamicat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/skatetocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/skatetocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/spidertocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/spidertocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/stormtroopocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/stormtroopocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/swagtocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/swagtocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/waldocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/waldocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/welcometocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/FullScreenImageTransition/FullScreenImageTransition/Resources/octocats/welcometocat.png -------------------------------------------------------------------------------- /FullScreenImageTransition/README.md: -------------------------------------------------------------------------------- 1 | # Transition images to full screen + zoomable image and stretchy header 2 | 3 | Check out [Transition images to full screen + zoomable image](https://medium.com/@thomsmed/transition-images-to-full-screen-animated-ios-f68261489c81)! 4 | 5 | The Octocat images used in this example project was downloaded from https://octodex.github.com/. 6 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWClient/GRPCFTWClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWClient/GRPCFTWClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWClient/GRPCFTWClient/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWClient/GRPCFTWClient/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWClient/GRPCFTWClient/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // GRPCFTWClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 06/06/2022. 6 | // 7 | 8 | import UIKit 9 | 10 | class ViewController: UIViewController { 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | // Do any additional setup after loading the view. 15 | } 16 | 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWClient/README.md: -------------------------------------------------------------------------------- 1 | # gRPC Swift (iOS) client 2 | 3 | ⚠️ This example project only contains some basic example code. And is meant to be used as an inspiration as is. 4 | 5 | It was used as a "playground" when writing up [5 Tips when getting started with gRPC and iOS](https://medium.com/@thomsmed/5-tips-when-getting-started-with-grpc-and-ios-9e4323bd6b98). 6 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWServer/GRPCFTWServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWServer/GRPCFTWServer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GRPCFTW/GRPCFTWServer/README.md: -------------------------------------------------------------------------------- 1 | # gRPC Swift server 2 | 3 | ⚠️ This example project only contains some basic example code. And is meant to be used as an inspiration as is. 4 | 5 | It was used to experiment while writing up [5 Tips when getting started with gRPC and iOS](https://medium.com/@thomsmed/5-tips-when-getting-started-with-grpc-and-ios-9e4323bd6b98). 6 | -------------------------------------------------------------------------------- /HTTPAPIProblem/HTTPAPIProblem.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HTTPAPIProblem/HTTPAPIProblem/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /HTTPAPIProblem/HTTPAPIProblem/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /HTTPAPIProblem/HTTPAPIProblem/HTTPAPIProblemApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HTTPAPIProblemApp.swift 3 | // HTTPAPIProblem 4 | // 5 | // Created by Thomas Smedmann on 07/01/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct HTTPAPIProblemApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /HTTPAPIProblem/HTTPAPIProblem/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /HTTPAPIProblem/README.md: -------------------------------------------------------------------------------- 1 | # Model and handle HTTP API Problems (RFC 9457) 2 | 3 | This example application showcase one possible way to model and handle HTTP API Problems, 4 | as defined by [RFC 9457](https://datatracker.ietf.org/doc/rfc9457/). 5 | 6 | The idea of an OpaqueValue is also touched upon. Stolen from [Representing arbitrary data (e.g JSON) as a custom and opaque Codable type](https://medium.com/@thomsmed/representing-arbitrary-data-e-g-json-as-a-custom-and-opaque-codable-type-dfaa07b22cd3). 7 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Model/ErrorBody.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ErrorBody.swift 3 | // HTTPClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 10/02/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | struct ErrorBody: Decodable { 11 | let title: String 12 | let message: String 13 | } 14 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Model/Item.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Item.swift 3 | // HTTPClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 10/02/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Item: Codable { 11 | let id: UUID 12 | let text: String 13 | } 14 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Networking/HTTPMethod.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HTTPMethod.swift 3 | // HTTPClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/02/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Enumeration representing possible HTTP Request Methods. 11 | public enum HTTPMethod: String { 12 | case get = "GET" 13 | case put = "PUT" 14 | case post = "POST" 15 | case delete = "DELETE" 16 | } 17 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Networking/HTTPMimeType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HTTPMimeType.swift 3 | // HTTPClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/02/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Enumeration representing possible HTTP MIME (Multipurpose Internet Mail Extensions) Types. 11 | public enum HTTPMimeType: String { 12 | case textHtml = "text/html; charset=utf-8" 13 | case applicationJson = "application/json; charset=utf-8" 14 | case applicationJoseJson = "application/jose+json; charset=utf-8" 15 | } 16 | -------------------------------------------------------------------------------- /HTTPClient/HTTPClient/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /HTTPClient/HTTPServer/.gitignore: -------------------------------------------------------------------------------- 1 | Packages 2 | .build 3 | xcuserdata 4 | *.xcodeproj 5 | DerivedData/ 6 | .DS_Store 7 | db.sqlite 8 | .swiftpm 9 | .env 10 | .env.* 11 | ! .env.example 12 | .vscode 13 | -------------------------------------------------------------------------------- /HTTPClient/HTTPServer/Sources/HTTPServer/configure.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | 3 | // configures your application 4 | public func configure(_ app: Application) async throws { 5 | // register routes 6 | try routes(app) 7 | } 8 | -------------------------------------------------------------------------------- /HTTPClient/HTTPServer/Sources/HTTPServer/entrypoint.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | import Logging 3 | 4 | @main 5 | enum Entrypoint { 6 | static func main() async throws { 7 | var env = try Environment.detect() 8 | try LoggingSystem.bootstrap(from: &env) 9 | 10 | let app = Application(env) 11 | defer { app.shutdown() } 12 | 13 | do { 14 | try await configure(app) 15 | } catch { 16 | app.logger.report(error: error) 17 | throw error 18 | } 19 | try await app.execute() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ImprovedContainerViewController/ImprovedContainerViewController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ImprovedContainerViewController/ImprovedContainerViewController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ImprovedContainerViewController/ImprovedContainerViewController/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ImprovedContainerViewController/ImprovedContainerViewController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ImprovedContainerViewController/README.md: -------------------------------------------------------------------------------- 1 | # Custom Container View Controller (improved) 2 | 3 | Example on how to create a custom Container View Controller ([SinglePageController](ImprovedContainerViewController/SinglePageController/SinglePageController.swift) and [SegmentedPageViewController](ImprovedContainerViewController/SegmentedPageViewController/SegmentedPageViewController.swift)), and constraining it's children using Auto Layout Constraints. 4 | 5 | Check out [Custom Container View Controller](https://medium.com/@thomsmed/custom-container-view-controller-89123e3f2df9) for a writeup @ Medium. 6 | -------------------------------------------------------------------------------- /InteractiveAnimations/InteractiveAnimations.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /InteractiveAnimations/InteractiveAnimations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /InteractiveAnimations/InteractiveAnimations/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /InteractiveAnimations/InteractiveAnimations/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /InteractiveAnimations/InteractiveAnimations/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /KeyboardAvoidance/KeyboardAvoidance.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KeyboardAvoidance/KeyboardAvoidance.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /KeyboardAvoidance/KeyboardAvoidance/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /KeyboardAvoidance/KeyboardAvoidance/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /KeyboardAvoidance/KeyboardAvoidance/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /KeyboardAvoidance/README.md: -------------------------------------------------------------------------------- 1 | # Keyboard Avoidance View Controller 2 | 3 | A basic and simple View Controller that automatically handle keyboard appearance / disappearance and makes sure content is not hidden behind the keyboard. 4 | The [KeyboardAvoidanceViewController](KeyboardAvoidance/KeyboardAvoidanceViewController.swift) View Controller is meant to be subclassed and have subviews added the its `contentView` property. 5 | 6 | Check out [Keyboard Avoidance View Controller](https://medium.com/@thomsmed/keyboard-avoidance-view-controller-c19112c6b66d)! 7 | -------------------------------------------------------------------------------- /KeychainStorage/KeychainStorage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KeychainStorage/KeychainStorage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /KeychainStorage/KeychainStorage/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /KeychainStorage/KeychainStorage/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /KeychainStorage/KeychainStorage/KeychainStorageApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeychainStorageApp.swift 3 | // KeychainStorage 4 | // 5 | // Created by Thomas Asheim Smedmann on 26/09/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct KeychainStorageApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /KeychainStorage/KeychainStorage/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /KeychainStorage/README.md: -------------------------------------------------------------------------------- 1 | # Securely store objects and values in Keychain 2 | 3 | A simple example on how to store various data types securely using the [Keychain Services API](https://developer.apple.com/documentation/security/keychain_services). 4 | -------------------------------------------------------------------------------- /LiveMockData/LiveMockData.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LiveMockData/LiveMockData.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LiveMockData/LiveMockData/EmojiRepository/EmojiRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EmojiRepository.swift 3 | // LiveMockData 4 | // 5 | // Created by Thomas Asheim Smedmann on 28/08/2022. 6 | // 7 | 8 | import Foundation 9 | import Combine 10 | 11 | typealias Emoji = String 12 | 13 | protocol EmojiRepository { 14 | var emojis: AnyPublisher<[Emoji], Never> { get } 15 | } 16 | -------------------------------------------------------------------------------- /LiveMockData/LiveMockData/MockData/emojis.json: -------------------------------------------------------------------------------- 1 | [ 2 | "😂", 3 | "😃", 4 | "😄", 5 | "😁", 6 | "😀", 7 | "😅", 8 | "😆", 9 | "🤣" 10 | ] 11 | -------------------------------------------------------------------------------- /LiveMockData/LiveMockData/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LiveMockData/LiveMockData/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /LiveMockData/LiveMockData/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LiveMockData/README.md: -------------------------------------------------------------------------------- 1 | # Live mock data 2 | 3 | An example on how to use [DispatchSource.makeFileSystemObjectSource(fileDescriptor:eventMask:queue:)](https://developer.apple.com/documentation/dispatch/dispatchsource/2300040-makefilesystemobjectsource) to monitor a file with mock data (json file in this case), so that editing file will cause a live update of the app running in a simulator. 4 | -------------------------------------------------------------------------------- /NetworkMonitoring/NetworkMonitoring.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NetworkMonitoring/NetworkMonitoring.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NetworkMonitoring/NetworkMonitoring/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NetworkMonitoring/NetworkMonitoring/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NetworkMonitoring/NetworkMonitoring/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /NetworkMonitoring/NetworkMonitoring/NetworkMonitoringApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkMonitoringApp.swift 3 | // NetworkMonitoring 4 | // 5 | // Created by Thomas Asheim Smedmann on 06/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct NetworkMonitoringApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetworkMonitoring/NetworkMonitoring/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /NetworkMonitoring/README.md: -------------------------------------------------------------------------------- 1 | # Network monitoring 2 | 3 | Simple network monitoring using [NWPathMonitor](https://developer.apple.com/documentation/network/nwpathmonitor). 4 | -------------------------------------------------------------------------------- /OpaqueValue/OpaqueValue.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OpaqueValue/OpaqueValue/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /OpaqueValue/OpaqueValue/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /OpaqueValue/OpaqueValue/OpaqueValueApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OpaqueValueApp.swift 3 | // OpaqueValue 4 | // 5 | // Created by Thomas Asheim Smedmann on 14/07/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct OpaqueValueApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /OpaqueValue/OpaqueValue/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /OpaqueValue/README.md: -------------------------------------------------------------------------------- 1 | # Representing arbitrary data as an opaque Codable type 2 | 3 | This example app illustrate the concept of an opaque Codable type that can represent arbitrary (Codable) data. E.g some arbitrary JSON. 4 | The type consists of one or more primitive types and/or one or more nested opaque values. 5 | 6 | This code is heavily inspired by [Rob Napier](https://stackoverflow.com/users/97337/rob-napier)'s answer to this [StackOverflow post](https://stackoverflow.com/questions/65901928/swift-jsonencoder-encoding-class-containing-a-nested-raw-json-object-literal). 7 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "swift-atomics", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/apple/swift-atomics.git", 7 | "state" : { 8 | "revision" : "cd142fd2f64be2100422d658e7411e39489da985", 9 | "version" : "1.2.0" 10 | } 11 | } 12 | ], 13 | "version" : 2 14 | } 15 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache.xctestplan: -------------------------------------------------------------------------------- 1 | { 2 | "configurations" : [ 3 | { 4 | "id" : "A212AF8E-3A86-4AB0-A9E9-B68B18215DF7", 5 | "name" : "Configuration 1", 6 | "options" : { 7 | 8 | } 9 | } 10 | ], 11 | "defaultOptions" : { 12 | 13 | }, 14 | "testTargets" : [ 15 | { 16 | "target" : { 17 | "containerPath" : "container:ResourceCache.xcodeproj", 18 | "identifier" : "ED14E0822B89FC0700F9CEA4", 19 | "name" : "ResourceCacheTests" 20 | } 21 | } 22 | ], 23 | "version" : 1 24 | } 25 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ResourceCache/ResourceCache/ResourceCacheApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceCacheApp.swift 3 | // ResourceCache 4 | // 5 | // Created by Thomas Asheim Smedmann on 24/02/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ResourceCacheApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SharedAppAuthState/README.md: -------------------------------------------------------------------------------- 1 | # Shared authentication state 2 | 3 | Check out [Share authentication state across your apps, App Clips and widgets](https://medium.com/@thomsmed/share-authentication-state-across-your-apps-app-clips-and-widgets-ios-e7e7f24e5525)! 4 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "platform" : "universal", 6 | "reference" : "systemOrangeColor" 7 | }, 8 | "idiom" : "universal" 9 | } 10 | ], 11 | "info" : { 12 | "author" : "xcode", 13 | "version" : 1 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/172.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/196.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/216.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/48.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/55.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthState/Assets.xcassets/AppIcon.appiconset/88.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Auth/AuthError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthError.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | 10 | enum AuthError: Error { 11 | case missingConfiguration 12 | case notAuthenticated 13 | case failedToPersistState 14 | } 15 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Auth/AuthService/AuthService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthService.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import Combine 11 | 12 | protocol AuthService: AnyObject { 13 | func login(_ completion: @escaping (Result) -> Void) 14 | func logout() 15 | var hasSignedInBefore: Bool { get } 16 | } 17 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Auth/AuthStateRepository/AuthStateRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthStateRepository.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | import AppAuth 10 | 11 | protocol AuthStateRepository: AnyObject { 12 | var state: OIDAuthState? { get } 13 | func persist(state: OIDAuthState) throws 14 | func clear() 15 | } 16 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/Auth/AuthTokenProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthTokenProvider.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AuthTokenProvider: AnyObject { 11 | func performWithFreshToken(_ action: @escaping (Result) -> Void) 12 | } 13 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthState/SharedAppAuthState.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.mydomain.shared 8 | 9 | keychain-access-groups 10 | 11 | $(AppIdentifierPrefix)com.mydomain.shared 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "platform" : "universal", 6 | "reference" : "systemGreenColor" 7 | }, 8 | "idiom" : "universal" 9 | } 10 | ], 11 | "info" : { 12 | "author" : "xcode", 13 | "version" : 1 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/172.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/196.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/216.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/48.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/55.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/AppIcon.appiconset/88.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppClip 6 | 7 | NSAppClipRequestEphemeralUserNotification 8 | 9 | NSAppClipRequestLocationConfirmation 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/SharedAppAuthStateAppClip.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.parent-application-identifiers 6 | 7 | $(AppIdentifierPrefix)ios.example.SharedAppAuthState 8 | 9 | com.apple.security.application-groups 10 | 11 | group.com.mydomain.shared 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateAppClip/SharedAppAuthStateAppClipApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharedAppAuthStateAppClipApp.swift 3 | // SharedAppAuthStateAppClip 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct SharedAppAuthStateAppClipApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "platform" : "universal", 6 | "reference" : "systemPinkColor" 7 | }, 8 | "idiom" : "universal" 9 | } 10 | ], 11 | "info" : { 12 | "author" : "xcode", 13 | "version" : 1 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/172.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/196.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/216.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/48.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/55.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/AppIcon.appiconset/88.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Auth/AuthError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthError.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | 10 | enum AuthError: Error { 11 | case missingConfiguration 12 | case notAuthenticated 13 | case failedToPersistState 14 | } 15 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Auth/AuthService/AuthService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthService.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import Combine 11 | 12 | protocol AuthService: AnyObject { 13 | func login(_ completion: @escaping (Result) -> Void) 14 | func logout() 15 | var hasSignedInBefore: Bool { get } 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Auth/AuthStateRepository/AuthStateRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthStateRepository.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | import AppAuth 10 | 11 | protocol AuthStateRepository: AnyObject { 12 | var state: OIDAuthState? { get } 13 | func persist(state: OIDAuthState) throws 14 | func clear() 15 | } 16 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/Auth/AuthTokenProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthTokenProvider.swift 3 | // SharedAppAuthState 4 | // 5 | // Created by Thomas Asheim Smedmann on 30/12/2021. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol AuthTokenProvider: AnyObject { 11 | func performWithFreshToken(_ action: @escaping (Result) -> Void) 12 | } 13 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateSecondApp/SharedAppAuthStateSecondApp.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)com.mydomain.shared 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/172.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/196.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/216.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/48.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/55.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/AppIcon.appiconset/88.png -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidget/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.widgetkit-extension 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SharedAppAuthState/SharedAppAuthStateWidgetExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)com.mydomain.shared 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SignalingStorage/SignalingStorage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SignalingStorage/SignalingStorage/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SignalingStorage/SignalingStorage/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SignalingStorage/SignalingStorage/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SignalingStorage/SignalingStorage/SignalingStorageApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SignalingStorageApp.swift 3 | // SignalingStorage 4 | // 5 | // Created by Thomas Smedmann on 23/03/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct SignalingStorageApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/README.md: -------------------------------------------------------------------------------- 1 | # Stretchy table header view 2 | 3 | Check out [Stretchy table header view](https://medium.com/@thomsmed/stretchy-table-header-view-ios-635a0e95d3c5)! 4 | 5 | The Octocat images used in this example project was downloaded from https://octodex.github.com/. 6 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "TinyConstraints", 6 | "repositoryURL": "git@github.com:roberthein/TinyConstraints.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "3262e5c591d4ab6272255df2087a01bbebd138dc", 10 | "version": "4.0.2" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Assets.xcassets/octocats.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "octocats.jpeg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Assets.xcassets/octocats.imageset/octocats.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Assets.xcassets/octocats.imageset/octocats.jpeg -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/filmtocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/filmtocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/goretocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/goretocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/jetpacktocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/jetpacktocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/manufacturetocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/manufacturetocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/murakamicat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/murakamicat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/skatetocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/skatetocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/spidertocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/spidertocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/stormtroopocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/stormtroopocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/swagtocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/swagtocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/waldocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/waldocat.png -------------------------------------------------------------------------------- /StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/welcometocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomsmed/ios-examples/4c4c5b6bca18d970041a8d32f2239c298317a2ad/StretchyTableViewHeader/StretchyTableViewHeader/Resources/octocats/welcometocat.png -------------------------------------------------------------------------------- /SwiftUIHTML/SwiftUIHTML.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftUIHTML/SwiftUIHTML.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftUIHTML/SwiftUIHTML/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SwiftUIHTML/SwiftUIHTML/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SwiftUIHTML/SwiftUIHTML/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIHTML/SwiftUIHTML/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIHTML/SwiftUIHTML/SwiftUIHTMLApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIHTMLApp.swift 3 | // SwiftUIHTML 4 | // 5 | // Created by Thomas Asheim Smedmann on 09/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct SwiftUIHTMLApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /VerticalSlices/VerticalSlices.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /VerticalSlices/VerticalSlices/Features/Explore/ExploreView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExploreView.swift 3 | // VerticalSlices 4 | // 5 | // Created by Thomas Smedmann on 09/11/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ExploreView: View { 11 | var body: some View { 12 | Text("Explore") 13 | } 14 | } 15 | 16 | #Preview { 17 | ExploreView() 18 | } 19 | -------------------------------------------------------------------------------- /VerticalSlices/VerticalSlices/Features/Home/Profile/ProfileView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileView.swift 3 | // VerticalSlices 4 | // 5 | // Created by Thomas Asheim Smedmann on 21/10/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ProfileView: View { 11 | var body: some View { 12 | VStack { 13 | Text("Profile") 14 | } 15 | } 16 | } 17 | 18 | #Preview { 19 | ProfileView() 20 | } 21 | -------------------------------------------------------------------------------- /VerticalSlices/VerticalSlices/Features/Login/LoginView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoginView.swift 3 | // VerticalSlices 4 | // 5 | // Created by Thomas Asheim Smedmann on 21/10/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct LoginView: View { 11 | var body: some View { 12 | NavigationStack { 13 | VStack { 14 | Text("Login") 15 | } 16 | } 17 | } 18 | } 19 | 20 | #Preview { 21 | LoginView() 22 | } 23 | -------------------------------------------------------------------------------- /VerticalSlices/VerticalSlices/Features/More/MoreView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoreView.swift 3 | // VerticalSlices 4 | // 5 | // Created by Thomas Asheim Smedmann on 21/10/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MoreView: View { 11 | var body: some View { 12 | NavigationStack { 13 | VStack { 14 | Text("More") 15 | } 16 | } 17 | } 18 | } 19 | 20 | #Preview { 21 | MoreView() 22 | } 23 | -------------------------------------------------------------------------------- /VerticalSlices/VerticalSlices/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /VerticalSlices/VerticalSlices/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ViewModelHierarchy/ViewModelHierarchy.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ViewModelHierarchy/ViewModelHierarchy/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ViewModelHierarchy/ViewModelHierarchy/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ViewModelHierarchy/ViewModelHierarchy/Feature/Main/Home/Profile/ProfileView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileView.swift 3 | // ViewModelHierarchy 4 | // 5 | // Created by Thomas Asheim Smedmann on 23/07/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ProfileView: View { 11 | var body: some View { 12 | ScrollView { 13 | VStack { 14 | Text("Profile name") 15 | .padding() 16 | 17 | Text("Profile details") 18 | .padding() 19 | } 20 | } 21 | .navigationTitle("Profile") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ViewModelHierarchy/ViewModelHierarchy/Feature/Main/More/Details/DetailsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailsCoordinatorView.swift 3 | // ViewModelHierarchy 4 | // 5 | // Created by Thomas Asheim Smedmann on 23/07/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct DetailsView: View { 11 | var body: some View { 12 | ScrollView { 13 | VStack { 14 | Text("Details") 15 | .padding() 16 | } 17 | } 18 | .navigationTitle("Details") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ViewModelHierarchy/ViewModelHierarchy/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ViewModelHierarchy/ViewModelHierarchy/ViewModelHierarchy.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.associated-domains 6 | 7 | applinks:ios.example.ViewModelHierarchy?mode=developer 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient/Model/IncomingMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IncomingMessage.swift 3 | // WebSocketClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 17/02/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum IncomingMessage: Decodable { 11 | case items(items: [Item]) 12 | case update(item: Item) 13 | case add(item: Item) 14 | case delete(item: Item) 15 | } 16 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient/Model/Item.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Item.swift 3 | // WebSocketClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 13/02/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Item: Codable { 11 | let id: UUID 12 | let text: String 13 | } 14 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient/Model/OutgoingMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OutgoingMessage.swift 3 | // WebSocketClient 4 | // 5 | // Created by Thomas Asheim Smedmann on 17/02/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum OutgoingMessage: Encodable { 11 | case update(item: Item) 12 | case add(item: Item) 13 | case delete(id: UUID) 14 | } 15 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketClient/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketServer/.gitignore: -------------------------------------------------------------------------------- 1 | Packages 2 | .build 3 | xcuserdata 4 | *.xcodeproj 5 | DerivedData/ 6 | .DS_Store 7 | db.sqlite 8 | .swiftpm 9 | .env 10 | .env.* 11 | ! .env.example 12 | .vscode 13 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketServer/Sources/WebSocketServer/configure.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | 3 | // configures your application 4 | public func configure(_ app: Application) async throws { 5 | // register routes 6 | try routes(app) 7 | } 8 | -------------------------------------------------------------------------------- /WebSocketClient/WebSocketServer/Sources/WebSocketServer/entrypoint.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | import Logging 3 | 4 | @main 5 | enum Entrypoint { 6 | static func main() async throws { 7 | var env = try Environment.detect() 8 | try LoggingSystem.bootstrap(from: &env) 9 | 10 | let app = Application(env) 11 | defer { app.shutdown() } 12 | 13 | do { 14 | try await configure(app) 15 | } catch { 16 | app.logger.report(error: error) 17 | throw error 18 | } 19 | try await app.execute() 20 | } 21 | } 22 | --------------------------------------------------------------------------------