├── .gitignore ├── AngularGradientApp ├── AngularGradientApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── AngularGradientApp │ ├── AngularGradientAppApp.swift │ ├── AnimateAnglesView.swift │ ├── AnimateCenterAnglesView.swift │ ├── AnimateCenterView.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── CenterOptionsView.swift │ ├── CircleView.swift │ ├── ContentView.swift │ ├── FourCornersView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── StartAngularGradientView.swift │ ├── StartEndAngleView.swift │ ├── ThumbView.swift │ └── Utilities.swift ├── README.md └── images │ ├── angular-gradient-four-corners.png │ ├── animate-circle-angular-gradient.gif │ └── animate-start-end-angles-center-angular-gradient.gif ├── ArraySliceApp ├── ArraySliceApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ericcallanan.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ericcallanan.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── ArraySliceApp │ ├── ArraySliceAppApp.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── PrefixNoErrorView.swift │ ├── PrefixThroughView.swift │ ├── PrefixUptoView.swift │ ├── PrefixView.swift │ ├── PrefixWhileView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── SliceErrorView.swift │ ├── SliceMidView.swift │ ├── SliceStartView.swift │ ├── ThumbView.swift │ └── vviews │ │ ├── ArraySliceView.swift │ │ ├── CellView.swift │ │ ├── ErrorView.swift │ │ ├── LabelView.swift │ │ ├── LargeCellView.swift │ │ ├── OriginalArrayView.swift │ │ └── TitleView.swift ├── README.md └── images │ ├── array-slice-prefix-no-error.png │ ├── array-slice-range.png │ └── arrayslice-thumb.png ├── AsyncLetApp ├── AsyncLetApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── AsyncLetApp │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── AsyncLetAppApp.swift │ ├── MainView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── version1 │ │ ├── models │ │ │ └── DataFile.swift │ │ ├── viewModels │ │ │ ├── DataFileViewModel.swift │ │ │ ├── DataFileViewModel2.swift │ │ │ ├── DataFileViewModel3.swift │ │ │ └── DataFileViewModel4.swift │ │ └── views │ │ │ ├── AsynchronousView.swift │ │ │ ├── ButtonView.swift │ │ │ ├── ParallelView.swift │ │ │ ├── SequentialView.swift │ │ │ ├── SynchronousView.swift │ │ │ └── TitleView.swift │ └── version2 │ │ ├── viewModels │ │ ├── DataFileViewMode7.swift │ │ ├── DataFileViewModel5.swift │ │ ├── DataFileViewModel6.swift │ │ └── DataFileViewModel8.swift │ │ └── views │ │ ├── CancelFlagView.swift │ │ ├── CancelTaskMultipleView.swift │ │ ├── CancelTaskView.swift │ │ └── NaiveCancelView.swift ├── README.md └── images │ ├── Asynchronous-download-in-multiple-files-in-parallel.gif │ ├── Asynchronous-download-in-parallel.png │ ├── cancel-resume-multiple-tasks.gif │ ├── cancel-task-cascade.png │ └── synchronous-download-simulation.png ├── BarChartSection.swift ├── BarChartView.swift ├── CircularSliderView.swift ├── CircularSliderWithChatGpt4 ├── CircularSliderWithChatGpt4.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── CircularSliderWithChatGpt4 │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── CircularSliderWithChatGpt4App.swift │ ├── ContentView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── SliderView1.swift │ ├── SliderView10.swift │ ├── SliderView2.swift │ ├── SliderView3.swift │ ├── SliderView4.swift │ ├── SliderView5.swift │ ├── SliderView5a.swift │ ├── SliderView5b.swift │ ├── SliderView6.swift │ ├── SliderView7.swift │ ├── SliderView8.swift │ ├── SliderView9.swift │ └── ThumbView.swift ├── README.md └── images │ ├── chatgpt-navigation-multiple-prompts.png │ ├── circular-slider-multiple.gif │ ├── circular-slider-not-working.gif │ ├── circular-slider-working.gif │ └── multiple-circular-sliders.png ├── ColorConverterApp ├── ColorConverterApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ColorConverterApp │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Color+Hsb+Rgb.swift │ ├── ColorConverterAppApp.swift │ ├── ContentView.swift │ ├── DescriptionView.swift │ ├── GetHueView.swift │ ├── GetRedView.swift │ ├── HsbExtensionView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── SaturationAndBrightnessView.swift │ └── ThumbView.swift ├── README.md └── images │ ├── color-adjust-sat-bright.png │ └── convert-color-thumb.png ├── ColorGradientApp ├── ColorGradientApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ColorGradientApp │ ├── AngularGradientView.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── castle1.imageset │ │ │ ├── Contents.json │ │ │ └── castle1.png │ │ ├── castle2.imageset │ │ │ ├── Contents.json │ │ │ └── castle2.png │ │ ├── mountain1.imageset │ │ │ ├── Contents.json │ │ │ └── mountain1.png │ │ ├── mountain2.imageset │ │ │ ├── Contents.json │ │ │ └── mountain2.png │ │ ├── mountain3.imageset │ │ │ ├── Contents.json │ │ │ └── mountain3.png │ │ ├── mountain4.imageset │ │ │ ├── Contents.json │ │ │ └── mountain4.png │ │ └── mountain5.imageset │ │ │ ├── Contents.json │ │ │ └── mountain5.png │ ├── ColorBackgroundView.swift │ ├── ColorGradientAppApp.swift │ ├── ColorWithCardsView.swift │ ├── ContentView.swift │ ├── FullBackgroundView.swift │ ├── MaterialBackgroundView.swift │ ├── MaterialCardsView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── PurpleBackgroundView.swift │ └── ThumbView.swift ├── README.md └── images │ └── color-over-angular-gradient.png ├── ColorPencilsApp ├── ColorPencilsApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── ColorPencilsApp │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── BlueGradientPencilView.swift │ ├── BluePencilView.swift │ ├── ColorPencilSetView.swift │ ├── ColorPencilsAppApp.swift │ ├── ContentView.swift │ ├── GrayPencilView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ └── ThumbView.swift ├── README.md └── images │ └── rainbow-color-pencil-set.png ├── ColorSelectionHsb ├── ColorSelectionHsb.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ericcallanan.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ericcallanan.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── ColorSelectionHsb │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── ColorSelectionHsbApp.swift │ ├── ContentView.swift │ ├── Models │ └── ColorModel.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── ThumbView.swift │ ├── ViewModels │ └── ColorViewModel.swift │ └── Views │ ├── ChangeHsbView.swift │ ├── CircularSliderView.swift │ ├── ColorWheelView.swift │ ├── HsbColorPaletteView.swift │ ├── MatchingColorView.swift │ └── RgbColorPaletteView.swift ├── EmployeeNavigationSplitViewApp ├── EmployeeNavigationSplitViewApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ericcallanan.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ericcallanan.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── EmployeeNavigationSplitViewApp │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── ContentView.swift │ ├── EmployeeNavigationSplitViewApp.entitlements │ ├── EmployeeNavigationSplitViewAppApp.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── ThreeColumnDepartmentView.swift │ ├── ThreeColumnSingleView.swift │ ├── ThreeColumnView.swift │ ├── ThreeColumnVisibilityView.swift │ └── TwoColumnView.swift ├── GameOfLifeApp ├── GameOfLifeApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── GameOfLifeApp │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── CanvasFromArrayView.swift │ ├── CanvasFromModelView.swift │ ├── CanvasLayoutView.swift │ ├── ContentView.swift │ ├── GameOfLifeAppApp.swift │ ├── GameOfLifeView.swift │ ├── GridFromArrayView.swift │ ├── GridLayoutView.swift │ ├── LifeModel.swift │ ├── LifeViewModel.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── ThumbView.swift │ └── Utilities.swift ├── README.md └── images │ ├── canvas-layout-from-array.png │ ├── conways-game-of-life.gif │ └── game-of-life-view.png ├── HeartShape.swift ├── LineAreaChartView.swift ├── LinearGradientApp ├── LinearGradientApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── LinearGradientApp │ ├── AllStartEndLinearView.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── BlueColorPencilView.swift │ ├── ColorPencilView.swift │ ├── ContentView.swift │ ├── LinearGradientAppApp.swift │ ├── PencilSetView.swift │ ├── PencilTipGradientView.swift │ ├── PointCoordinateView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── StartEndLinearView.swift │ ├── StartLinearGradientView.swift │ ├── ThumbView.swift │ └── Utilities.swift ├── README.md └── images │ ├── all-linear-gradient-options.png │ ├── color-pencil-set.png │ └── linear-gradient.png ├── MathewEffectApp ├── MatthewEffectApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ericcallanan.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ericcallanan.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── MatthewEffectApp │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── MatthewEffectAppApp.swift │ ├── Models │ └── MatthewModel.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── ViewModels │ └── MatthewViewModel.swift │ └── Views │ ├── CoinBarChartView.swift │ ├── ContentView.swift │ ├── RunTransactionsView.swift │ ├── ScenarioFourView.swift │ ├── ScenarioOneView.swift │ ├── ScenarioThreeView.swift │ ├── ScenarioTwoView.swift │ ├── SettingsView.swift │ └── Styles.swift ├── PieChartApp ├── PieChartApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── PieChartApp │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── BarAndPieChartView.swift │ ├── BarChartView.swift │ ├── ContentView.swift │ ├── DonutChartSortedView.swift │ ├── DonutChartView.swift │ ├── DonutWithLabelsView.swift │ ├── IncomeData.swift │ ├── InteractiveDonutView.swift │ ├── PieChartAppApp.swift │ ├── PieChartColorsView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── RoundedSectorSpaceView.swift │ └── ThumbView.swift ├── README.md └── images │ ├── donut-chart.png │ ├── donut-interactive-chart-labels.png │ ├── interactive-donut-chart-with-labels.gif │ └── pie-chart.png ├── README.md ├── RadialGradientApp ├── README.md ├── RadialGradientApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── RadialGradientApp │ ├── AnimateCenterRadiiView.swift │ ├── AnimateCenterView.swift │ ├── AnimateRadiiView.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── CenterOptionsView.swift │ ├── ContentView.swift │ ├── HypnoticView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── RadialGradientAppApp.swift │ ├── RainbowView.swift │ ├── StartEndRadiusView.swift │ ├── StartRadialGradientView.swift │ ├── ThumbView.swift │ └── Utilities.swift └── images │ ├── change-center-start-end-radii.gif │ ├── radial-gradient.png │ ├── radial-iterating-through-colors.gif │ └── rainbow-with-radialgradient.png ├── ScrollEffectApp ├── README.md ├── ScrollEffectApp.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── ScrollEffectApp │ ├── Animal.swift │ ├── AnimalCardView.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── animal-01.imageset │ │ │ ├── Contents.json │ │ │ └── animal-01.png │ │ ├── animal-02.imageset │ │ │ ├── Contents.json │ │ │ └── animal-02.png │ │ ├── animal-03.imageset │ │ │ ├── Contents.json │ │ │ └── animal-03.png │ │ ├── animal-04.imageset │ │ │ ├── Contents.json │ │ │ └── animal-04.png │ │ ├── animal-05.imageset │ │ │ ├── Contents.json │ │ │ └── animal-05.png │ │ ├── animal-06.imageset │ │ │ ├── Contents.json │ │ │ └── animal-06.png │ │ ├── animal-07.imageset │ │ │ ├── Contents.json │ │ │ └── animal-07.png │ │ ├── animal-08.imageset │ │ │ ├── Contents.json │ │ │ └── animal-08.png │ │ ├── animal-09.imageset │ │ │ ├── Contents.json │ │ │ └── animal-09.png │ │ ├── animal-10.imageset │ │ │ ├── Contents.json │ │ │ └── animal-10.png │ │ ├── animal-11.imageset │ │ │ ├── Contents.json │ │ │ └── animal-11.png │ │ ├── animal-12.imageset │ │ │ ├── Contents.json │ │ │ └── animal-12.png │ │ ├── animal-13.imageset │ │ │ ├── Contents.json │ │ │ └── animal-13.png │ │ ├── animal-14.imageset │ │ │ ├── Contents.json │ │ │ └── animal-14.png │ │ ├── animal-15.imageset │ │ │ ├── Contents.json │ │ │ └── animal-15.png │ │ ├── animal-16.imageset │ │ │ ├── Contents.json │ │ │ └── animal-16.png │ │ ├── animal-17.imageset │ │ │ ├── Contents.json │ │ │ └── animal-17.png │ │ ├── animal-18.imageset │ │ │ ├── Contents.json │ │ │ └── animal-18.png │ │ ├── animal-19.imageset │ │ │ ├── Contents.json │ │ │ └── animal-19.png │ │ ├── animal-20.imageset │ │ │ ├── Contents.json │ │ │ └── animal-20.png │ │ ├── animal-21.imageset │ │ │ ├── Contents.json │ │ │ └── animal-21.png │ │ ├── animal-22.imageset │ │ │ ├── Contents.json │ │ │ └── animal-22.png │ │ ├── animal-23.imageset │ │ │ ├── Contents.json │ │ │ └── animal-23.png │ │ ├── animal-24.imageset │ │ │ ├── Contents.json │ │ │ └── animal-24.png │ │ ├── animal-25.imageset │ │ │ ├── Contents.json │ │ │ └── animal-25.png │ │ └── animals │ │ │ └── Contents.json │ ├── ContentView.swift │ ├── NoTransitionView.swift │ ├── OffsetTransitionView.swift │ ├── OpacityTransitionView.swift │ ├── PerspectiveView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── ScaleOpacityRotationView.swift │ ├── ScaleOpacityView.swift │ ├── ScaleTransitionView.swift │ ├── ScrollEffectApp.entitlements │ ├── ScrollEffectAppApp.swift │ ├── ThumbView.swift │ └── ViewAlignedView.swift └── images │ ├── card-scale-opacity-rotation-animation.gif │ ├── cards-no-transition-animation.gif │ ├── cards-scale-opacity-animation.gif │ └── cards-scale-opacity-transition.png ├── ScrollingChartsApp ├── README.md ├── ScrollingChartsApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── ericcallanan.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ericcallanan.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── ScrollingChartsApp │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── ContentView.swift │ ├── Date+Extensions.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── ScrollingChartsAppApp.swift │ ├── Styles.swift │ ├── WeightChartView1.swift │ ├── WeightChartView2.swift │ ├── WeightChartView3.swift │ ├── WeightChartView4.swift │ ├── WeightData.swift │ └── WeightViewModel.swift ├── StarShape.swift ├── TasksAppWithChatGpt ├── README.md ├── TasksAppWithChatGpt.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── TasksAppWithChatGpt │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── EditableTaskView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Task.swift │ ├── TaskListViewModel.swift │ ├── TaskView.swift │ ├── TaskViewModel.swift │ └── TasksAppWithChatGptApp.swift ├── TasksAppWithChatGptTests │ ├── TaskTests.swift │ └── TasksAppWithChatGptTests.swift └── images │ ├── edit-tasks-view.png │ ├── editing-tasks-not-working.gif │ ├── light-and-dark-mode.png │ ├── tasklist.png │ └── tasks-persisted.gif ├── TicTacToe ├── README.md ├── TicTacToe.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ ├── xcbaselines │ │ └── 9ADCA25E270EC1B9002DA2FA.xcbaseline │ │ │ ├── D3905B57-9DA6-4F5A-A259-337FFADB3DBE.plist │ │ │ └── Info.plist │ │ └── xcschemes │ │ └── TicTacToe.xcscheme ├── TicTacToe │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Test.colorset │ │ │ └── Contents.json │ │ ├── redgreen.imageset │ │ │ ├── 00_red_green_refactor_diagram.png │ │ │ └── Contents.json │ │ └── tictactoegrid.imageset │ │ │ ├── 01_tic_tac_toe_grid.png │ │ │ └── Contents.json │ ├── Models │ │ ├── TicBoardModel.swift │ │ └── TicGameModel.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── TicTacToeApp.swift │ ├── ViewModels │ │ └── TicViewModel.swift │ └── Views │ │ ├── ActivePlayerView.swift │ │ ├── GridView.swift │ │ ├── ShapesView.swift │ │ └── TicTacToeView.swift ├── TicTacToeTests │ ├── ModelTests │ │ ├── TicBoardModelTests.swift │ │ ├── TicGameModelPerformanceTests.swift │ │ └── TicGameModelTests.swift │ └── ViewModelTests │ │ └── TicViewModelTests.swift └── images │ ├── minimax-path-for-o-player-adjusted-scores.png │ └── tic-tac-toe.gif ├── images ├── BarChart-top-section.png ├── heart.png ├── horizontal-scroll-on-swift-charts.gif ├── matching-colors-with-hsb.png ├── star.png ├── steps-chart.png └── three-column-multi-select.png ├── save images to macOS.swift └── swift.gitignore /AngularGradientApp/AngularGradientApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp/AngularGradientAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AngularGradientAppApp.swift 3 | // AngularGradientApp 4 | // 5 | // Created by Eric Callanan on 10/06/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct AngularGradientAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp/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 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp/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 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp/CenterOptionsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CenterOptionsView.swift 3 | // AngularGradientApp 4 | // 5 | // Created by Eric Callanan on 10/06/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CenterOptionsView: View { 11 | var body: some View { 12 | ScrollView { 13 | VStack { 14 | Text("All Center Options") 15 | .font(.largeTitle) 16 | .fontWeight(.bold) 17 | Divider() 18 | 19 | VStack(alignment: .trailing) { 20 | ForEach(UnitPointType.allCases, id: \.self) { endinging in 21 | AngularGradientView(center: endinging) 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | 29 | struct CenterOptionsView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | CenterOptionsView() 32 | } 33 | } 34 | 35 | struct AngularGradientView: View { 36 | var center: UnitPointType 37 | 38 | var body: some View { 39 | HStack { 40 | VStack { 41 | Text("\(center.rawValue)").font(.title2) 42 | } 43 | RoundedRectangle(cornerRadius: 20) 44 | .fill( 45 | AngularGradient(colors: AppColors.rainbow, 46 | center: center.unitPoint) 47 | ) 48 | .frame(width: 100, height: 100) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // AngularGradientApp 4 | // 5 | // Created by Eric Callanan on 10/06/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: StartAngularGradientView(), label: {Text("01 Simple angular gradient")}) 15 | NavigationLink (destination: CenterOptionsView(), label: {Text("02 All center options")}) 16 | NavigationLink (destination: FourCornersView(), label: {Text("03 Four corners")}) 17 | NavigationLink (destination: AnimateCenterView(), label: {Text("04 Animate center change")}) 18 | NavigationLink (destination: StartEndAngleView(), label: {Text("05 Setting start and end angles")}) 19 | NavigationLink (destination: AnimateAnglesView(), label: {Text("06 Animate start and end angles")}) 20 | NavigationLink (destination: AnimateCenterAnglesView(), label: {Text("07 Animate center and angles")}) 21 | NavigationLink (destination: CircleView(), label: {Text("08 Angular gradient on a circle")}) 22 | } 23 | } 24 | } 25 | } 26 | 27 | struct ContentView_Previews: PreviewProvider { 28 | static var previews: some View { 29 | ContentView() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /AngularGradientApp/AngularGradientApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AngularGradientApp/images/angular-gradient-four-corners.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AngularGradientApp/images/angular-gradient-four-corners.png -------------------------------------------------------------------------------- /AngularGradientApp/images/animate-circle-angular-gradient.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AngularGradientApp/images/animate-circle-angular-gradient.gif -------------------------------------------------------------------------------- /AngularGradientApp/images/animate-start-end-angles-center-angular-gradient.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AngularGradientApp/images/animate-start-end-angles-center-angular-gradient.gif -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ArraySliceApp/ArraySliceApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp.xcodeproj/xcuserdata/ericcallanan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ArraySliceApp.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/ArraySliceAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArraySliceAppApp.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ArraySliceAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/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 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/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 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: SliceMidView(), label: {Text("01 SliceMidView")}) 15 | NavigationLink (destination: SliceStartView(), label: {Text("02 SliceStartView")}) 16 | NavigationLink (destination: SliceErrorView(), label: {Text("03 SliceErrorView")}) 17 | NavigationLink (destination: PrefixView(), label: {Text("04 PrefixView")}) 18 | NavigationLink (destination: PrefixNoErrorView(), label: {Text("05 PrefixNoErrorView")}) 19 | NavigationLink (destination: PrefixThroughView(), label: {Text("06 PrefixThroughView")}) 20 | NavigationLink (destination: PrefixUptoView(), label: {Text("07 PrefixUptoView")}) 21 | NavigationLink (destination: PrefixWhileView(), label: {Text("08 PrefixWhileView")}) 22 | NavigationLink (destination: ThumbView(), label: {Text("09 ThumbView")}) 23 | } 24 | } 25 | } 26 | } 27 | 28 | struct ContentView_Previews: PreviewProvider { 29 | static var previews: some View { 30 | ContentView() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/PrefixNoErrorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixNoErrorView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PrefixNoErrorView: View { 11 | let nums = [2, 7, 15, 8, 1] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | VStack() { 18 | TitleView(title: "Prefix - maxLength does NOT have to be a valid index") 19 | 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "Prefix(7)", 24 | label: "nums.prefix(7)", 25 | slice: nums.prefix(7)) 26 | 27 | ErrorView(title: "Array Slice [..<7]", 28 | error: "Swift/Array.swift:405: \nFatal error: Array index is out of range") 29 | } 30 | } 31 | .padding(.horizontal, 60) 32 | .padding() 33 | } 34 | } 35 | } 36 | 37 | struct PrefixNoErrorView_Previews: PreviewProvider { 38 | static var previews: some View { 39 | PrefixNoErrorView() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/PrefixThroughView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixThroughView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PrefixThroughView: View { 11 | let nums = [2, 7, 15, 8, 1, 6, 10, 14, 4, 11, 13, 12, 5, 3, 9] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | VStack() { 18 | TitleView(title: "prefix(through:)") 19 | 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "prefix(through: 7)", 24 | label: "nums.prefix(through: 7)", 25 | slice: nums.prefix(through: 7)) 26 | 27 | ArraySliceView(title: "Array Slice [...7]", 28 | label: "nums[...7]", 29 | slice: nums[...7]) 30 | } 31 | } 32 | .padding(.horizontal, 60) 33 | .padding() 34 | } 35 | } 36 | } 37 | 38 | struct PrefixThroughView_Previews: PreviewProvider { 39 | static var previews: some View { 40 | PrefixThroughView() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/PrefixUptoView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixUptoView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PrefixUptoView: View { 11 | let nums = [2, 7, 15, 8, 1, 6, 10, 14, 4, 11, 13, 12, 5, 3, 9] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | VStack() { 18 | TitleView(title: "prefix(upTo:)") 19 | 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "prefix(upTo: 7)", 24 | label: "nums.prefix(upTo: 7)", 25 | slice: nums.prefix(upTo: 7)) 26 | 27 | ArraySliceView(title: "Array Slice [..<7]", 28 | label: "nums[..<7]", 29 | slice: nums[..<7]) 30 | } 31 | } 32 | .padding(.horizontal, 60) 33 | .padding() 34 | } 35 | } 36 | } 37 | 38 | struct PrefixUptoView_Previews: PreviewProvider { 39 | static var previews: some View { 40 | PrefixUptoView() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/PrefixView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PrefixView: View { 11 | let nums = [2, 7, 15, 8, 1, 6, 10, 14, 4, 11, 13, 12, 5, 3, 9] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | VStack() { 18 | TitleView(title: "Prefix returns the begining elements of an array") 19 | 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "Prefix(7)", 24 | label: "nums.prefix(7)", 25 | slice: nums.prefix(7)) 26 | 27 | ArraySliceView(title: "Array Slice [..<7]", 28 | label: "nums[..<7]", 29 | slice: nums[..<7]) 30 | } 31 | } 32 | .padding(.horizontal, 60) 33 | .padding() 34 | } 35 | } 36 | } 37 | 38 | struct PrefixView_Previews: PreviewProvider { 39 | static var previews: some View { 40 | PrefixView() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/PrefixWhileView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixWhileView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PrefixWhileView: View { 11 | let nums = [2, 7, 15, 8, 1, 6, 10, 14, 4, 11, 13, 12, 5, 3, 9] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | VStack() { 18 | TitleView(title: "prefix(while:)") 19 | 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "prefix(while:)", 24 | label: "nums.prefix(while: {$0 != 6})", 25 | slice: nums.prefix(while: {$0 != 6}), 26 | labelWidth: 450) 27 | 28 | ArraySliceView(title: "prefix(while:)", 29 | label: "nums.prefix(while: {$0 < 10})", 30 | slice: nums.prefix(while: {$0 < 10}), 31 | labelWidth: 450) 32 | } 33 | } 34 | .padding(.horizontal, 60) 35 | .padding() 36 | } 37 | } 38 | } 39 | 40 | struct PrefixWhileView_Previews: PreviewProvider { 41 | static var previews: some View { 42 | PrefixWhileView() 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/SliceErrorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SliceErrorView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SliceErrorView: View { 11 | let nums = [2, 7, 15, 8, 1] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | VStack() { 18 | TitleView(title: "Array Slice requires a valid index") 19 | 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "Array Slice [..<4]", 24 | label: "nums[..<4]", 25 | slice: nums[..<4]) 26 | 27 | ErrorView(title: "Array Slice [..<7]", 28 | error: "Swift/Array.swift:405: \nFatal error: Array index is out of range") 29 | } 30 | } 31 | .padding(.horizontal, 60) 32 | .padding() 33 | } 34 | } 35 | } 36 | 37 | struct SliceErrorView_Previews: PreviewProvider { 38 | static var previews: some View { 39 | SliceErrorView() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/SliceMidView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SliceMidView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SliceMidView: View { 11 | let nums = [2, 7, 15, 8, 1, 6, 10, 14, 4, 11, 13, 12, 5, 3, 9] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | VStack() { 18 | TitleView(title: "Array Slice using range subscript") 19 | 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "Array Slice [5..<9]", 24 | label: "nums[5..<9]", 25 | slice: nums[5..<9]) 26 | 27 | ArraySliceView(title: "Array Slice [5...9]", 28 | label: "nums[5...9]", 29 | slice: nums[5...9]) 30 | 31 | } 32 | } 33 | .padding(.horizontal, 60) 34 | .padding() 35 | } 36 | } 37 | } 38 | 39 | struct SliceMidView_Previews: PreviewProvider { 40 | static var previews: some View { 41 | SliceMidView() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/SliceStartView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SliceStartView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SliceStartView: View { 11 | let nums = [2, 7, 15, 8, 1, 6, 10, 14, 4, 11, 13, 12, 5, 3, 9] 12 | var body: some View { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | 18 | VStack() { 19 | TitleView(title: "Array Slice at begining or end") 20 | ScrollView { 21 | OriginalArrayView(nums: nums) 22 | 23 | ArraySliceView(title: "Array Slice [..<7]", 24 | label: "nums[..<7]", 25 | slice: nums[..<7]) 26 | 27 | ArraySliceView(title: "Array Slice [...7]", 28 | label: "nums[...7]", 29 | slice: nums[...7]) 30 | 31 | ArraySliceView(title: "Array Slice [7...]", 32 | label: "nums[7...]", 33 | slice: nums[7...]) 34 | } 35 | } 36 | .padding(.horizontal, 60) 37 | .padding() 38 | } 39 | } 40 | } 41 | 42 | struct SliceStartView_Previews: PreviewProvider { 43 | static var previews: some View { 44 | SliceStartView() 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/vviews/ArraySliceView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArraySliceView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ArraySliceView: View { 11 | var title: String 12 | var label: String 13 | var slice: ArraySlice 14 | var labelWidth: CGFloat = 350 15 | 16 | var body: some View { 17 | VStack(alignment: .leading, spacing: 20) { 18 | Divider() 19 | Text(title).font(.largeTitle).fontWeight(.bold) 20 | HStack(spacing:0) { 21 | LabelView(value: label, width: labelWidth) 22 | ForEach(slice, id: \.self) { 23 | CellView(value: "\($0)") 24 | } 25 | } 26 | HStack(spacing:0) { 27 | LabelView(value: "ArraySlice Indices", width: labelWidth) 28 | ForEach(slice.indices, id: \.self) { 29 | CellView(value: "\($0)", bgColor: .clear, borderColor: .yellow) 30 | } 31 | } 32 | Spacer().frame(height: 30) 33 | } 34 | } 35 | } 36 | 37 | struct ArraySliceView_Previews: PreviewProvider { 38 | static var previews: some View { 39 | ArraySliceView(title: "Title", label: "label", slice: [1,2,3,4]) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/vviews/CellView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CellView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CellView: View { 11 | var value: String 12 | var bgColor = Color(hue: 0.75, saturation: 0.30, brightness: 1.00) 13 | var borderColor = Color(hue: 0.74, saturation: 1.00, brightness: 0.30) 14 | 15 | var body: some View { 16 | RoundedRectangle(cornerRadius: 5) 17 | .fill(bgColor) 18 | .frame(width: 50, height: 50) 19 | .overlay { 20 | ZStack { 21 | RoundedRectangle(cornerRadius: 5) 22 | .strokeBorder(borderColor, style: StrokeStyle(lineWidth: 2, dash: [4, 5])) 23 | Text(value) 24 | .font(.title) 25 | .fontWeight(.bold) 26 | } 27 | } 28 | } 29 | } 30 | 31 | struct CellView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | CellView(value: "42") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/vviews/ErrorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ErrorView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ErrorView: View { 11 | var title: String 12 | var error: String 13 | 14 | var body: some View { 15 | VStack(alignment: .leading, spacing: 20) { 16 | Divider() 17 | Text(title).font(.largeTitle).fontWeight(.bold) 18 | Text("FATAL ERROR").font(.largeTitle).fontWeight(.medium).foregroundColor(.red) 19 | Text(error).font(.title).fontWeight(.medium).multilineTextAlignment(.leading) 20 | } 21 | } 22 | } 23 | 24 | struct ErrorView_Previews: PreviewProvider { 25 | static var previews: some View { 26 | ErrorView(title: "Title", error: "Error description") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/vviews/LabelView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct LabelView: View { 11 | var value: String 12 | var width: CGFloat = 350 13 | 14 | var body: some View { 15 | HStack { 16 | Spacer() 17 | Text(value) 18 | .font(.title) 19 | .fontWeight(.medium) 20 | .padding(.horizontal, 20) 21 | } 22 | .frame(width: width, height: 60) 23 | } 24 | } 25 | 26 | struct LabelView_Previews: PreviewProvider { 27 | static var previews: some View { 28 | LabelView(value: "some label") 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/vviews/LargeCellView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LargeCellView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct LargeCellView: View { 11 | var value: String 12 | var bgColor = Color(hue: 0.75, saturation: 0.30, brightness: 1.00) 13 | var borderColor = Color.green 14 | 15 | var body: some View { 16 | RoundedRectangle(cornerRadius: 5) 17 | .fill(bgColor) 18 | .frame(width: 120, height: 120) 19 | .overlay { 20 | ZStack { 21 | RoundedRectangle(cornerRadius: 5) 22 | .strokeBorder(borderColor, style: StrokeStyle(lineWidth: 4, dash: [4, 5])) 23 | Text(value) 24 | .font(.system(size: 60)) 25 | .fontWeight(.heavy) 26 | } 27 | } 28 | } 29 | } 30 | 31 | struct LargeCellView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | LargeCellView(value: "99") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/vviews/OriginalArrayView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OriginalArrayView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct OriginalArrayView: View { 11 | var nums: [Int] 12 | 13 | var body: some View { 14 | HStack { 15 | VStack(alignment: .leading, spacing: 20) { 16 | Text("Original Array").font(.largeTitle).fontWeight(.bold) 17 | HStack(spacing:0) { 18 | ForEach(nums, id: \.self) { 19 | CellView(value: "\($0)") 20 | } 21 | } 22 | Text("Array Indices").font(.largeTitle).fontWeight(.medium) 23 | HStack(spacing:0) { 24 | ForEach(nums.indices, id: \.self) { 25 | CellView(value: "\($0)", 26 | bgColor: .clear, 27 | borderColor: Color(hue: 0.10, saturation: 0.90, brightness: 1.00)) 28 | } 29 | } 30 | Spacer().frame(height: 40) 31 | } 32 | Spacer() 33 | } 34 | } 35 | } 36 | 37 | struct OriginalArrayView_Previews: PreviewProvider { 38 | static var previews: some View { 39 | OriginalArrayView(nums: [1,2,3,4]) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ArraySliceApp/ArraySliceApp/vviews/TitleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TitleView.swift 3 | // ArraySliceApp 4 | // 5 | // Created by Eric Callanan on 09/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TitleView: View { 11 | var title: String 12 | var body: some View { 13 | VStack { 14 | RoundedRectangle(cornerRadius: 25) 15 | .fill(Color(hue: 0.65, saturation: 0.8, brightness: 0.5)) 16 | .overlay { 17 | Text(title) 18 | .font(.largeTitle) 19 | .fontWeight(.bold) 20 | .foregroundColor(Color(hue: 0.15, saturation: 0.5, brightness: 1.0)) 21 | } 22 | .frame(height:80) 23 | 24 | Spacer().frame(height: 30) 25 | } 26 | } 27 | } 28 | 29 | struct TitleView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | TitleView(title: "Title") 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ArraySliceApp/README.md: -------------------------------------------------------------------------------- 1 | ## ArraySlice with range operator and Prefix in Swift 2 | 3 | 4 | The Swift standard library provides an ArraySlice to work with a subset of a larger 5 | collection without the overhead of making a copy of the original collection. 6 | Retrieving the first few elements of a collection can be achieved using the one-sided 7 | range operator, but is safer to use the prefix method without having to worry about 8 | an index out of range exception. 9 | 10 | This iPad app visualises ArraySlices using range operator and Prefix method. 11 | 12 | 13 | 14 | ### ArraySlice 15 | ArraySlice Thumbnail 18 | 19 | 20 | ### ArraySlice using Range operator 21 | array-slice-range 24 | 25 | 26 | ### ArraySlice using Prefix 27 | array-slice-prefix-no-error 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 |
39 | 40 | 41 | Full article is 42 | ArraySlice with range operator and Prefix in Swift 43 | 44 | -------------------------------------------------------------------------------- /ArraySliceApp/images/array-slice-prefix-no-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ArraySliceApp/images/array-slice-prefix-no-error.png -------------------------------------------------------------------------------- /ArraySliceApp/images/array-slice-range.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ArraySliceApp/images/array-slice-range.png -------------------------------------------------------------------------------- /ArraySliceApp/images/arrayslice-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ArraySliceApp/images/arrayslice-thumb.png -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/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 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/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 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/AsyncLetAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AsyncLetAppApp.swift 3 | // AsyncLetApp 4 | // 5 | // Created by Eric Callanan on 11/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct AsyncLetAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | MainView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/version1/models/DataFile.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataFile.swift 3 | // AsyncLetApp 4 | // 5 | // Created by Eric Callanan on 11/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct DataFile : Identifiable, Equatable { 11 | var id: Int 12 | var fileSize: Int 13 | var downloadedSize = 0 14 | var isDownloading = false 15 | 16 | init(id: Int, fileSize: Int) { 17 | self.id = id 18 | self.fileSize = fileSize 19 | } 20 | 21 | var progress: Double { 22 | return Double(self.downloadedSize) / Double(self.fileSize) 23 | } 24 | 25 | mutating func increment() { 26 | if downloadedSize < fileSize { 27 | downloadedSize += 1 28 | } else { 29 | isDownloading = false 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/version1/viewModels/DataFileViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataFileViewModel.swift 3 | // AsyncLetApp 4 | // 5 | // Created by Eric Callanan on 11/01/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | 11 | class DataFileViewModel: ObservableObject { 12 | @Published private(set) var file: DataFile 13 | 14 | init() { 15 | self.file = DataFile(id: 1, fileSize: 10) 16 | } 17 | 18 | func downloadFile() { 19 | file.isDownloading = true 20 | 21 | for _ in 0.. Int { 18 | await MainActor.run { 19 | file.isDownloading = true 20 | } 21 | 22 | for _ in 0.. some View { 32 | configuration.label 33 | .foregroundColor(.white) 34 | .padding(5) 35 | .frame(width:180, height: 40) 36 | .background(isEnabled ? Color(hue: 0.65, saturation: 0.8, brightness: 0.5) : Color.gray) 37 | .cornerRadius(10) 38 | .padding(10) 39 | .shadow(color: isEnabled ? .black : .black.opacity(0.8), 40 | radius: isEnabled ? 3 : 5, 41 | x: isEnabled ? 3.0 : -1.0, 42 | y: isEnabled ? 3.0 : -1.0) 43 | .scaleEffect(configuration.isPressed ? 0.95 : isEnabled ? 1.0 : 0.95) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/version1/views/TitleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TitleView.swift 3 | // AsyncLetApp 4 | // 5 | // Created by Eric Callanan on 11/01/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TitleView: View { 11 | var title: [String] 12 | var body: some View { 13 | VStack { 14 | let titleHeight: CGFloat = CGFloat(40 + (40 * title.count)) 15 | RoundedRectangle(cornerRadius: 25) 16 | .fill(Color(hue: 0.65, saturation: 0.8, brightness: 0.5)) 17 | .overlay { 18 | Text(title.joined(separator: "\n")) 19 | .font(.largeTitle) 20 | .fontWeight(.bold) 21 | .foregroundColor(Color(hue: 0.15, saturation: 0.5, brightness: 1.0)) 22 | .lineLimit(5) 23 | .multilineTextAlignment(.center) 24 | } 25 | .frame(height: titleHeight) 26 | 27 | Spacer().frame(height: 30) 28 | } 29 | .padding() 30 | } 31 | } 32 | 33 | struct TitleView_Previews: PreviewProvider { 34 | static var previews: some View { 35 | VStack { 36 | TitleView(title: ["Test1"]) 37 | 38 | TitleView(title: ["Test1", "Test2"]) 39 | 40 | TitleView(title: ["Test 2", "Test 2", "Test 3"]) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /AsyncLetApp/AsyncLetApp/version2/viewModels/DataFileViewModel5.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataFileViewModel5.swift 3 | // AsyncLetApp 4 | // 5 | // Created by Eric Callanan on 22/01/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | class DataFileViewModel5: ObservableObject { 11 | @Published private(set) var file: DataFile 12 | 13 | init() { 14 | self.file = DataFile(id: 1, fileSize: 10) 15 | } 16 | 17 | func downloadFile() async -> Int { 18 | await MainActor.run { 19 | file.isDownloading = true 20 | } 21 | 22 | for _ in 0.. Int { 20 | await MainActor.run { 21 | file.isDownloading = true 22 | } 23 | 24 | while await !cancelFlag, file.isDownloading { 25 | await MainActor.run { 26 | print(" -- Downloading file - \(file.progress * 100) %") 27 | file.increment() 28 | } 29 | usleep(300000) 30 | } 31 | 32 | await MainActor.run { 33 | file.isDownloading = false 34 | print(" ***** File : \(file.id) setting isDownloading to FALSE") 35 | } 36 | 37 | return 1 38 | } 39 | 40 | @MainActor 41 | func cancel() { 42 | self.cancelFlag = true 43 | print(" ***** File : \(file.id) setting cancelFlag to TRUE") 44 | self.reset() 45 | } 46 | 47 | @MainActor 48 | func reset() { 49 | self.file = DataFile(id: 1, fileSize: 10) 50 | self.cancelFlag = false 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /AsyncLetApp/images/Asynchronous-download-in-multiple-files-in-parallel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AsyncLetApp/images/Asynchronous-download-in-multiple-files-in-parallel.gif -------------------------------------------------------------------------------- /AsyncLetApp/images/Asynchronous-download-in-parallel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AsyncLetApp/images/Asynchronous-download-in-parallel.png -------------------------------------------------------------------------------- /AsyncLetApp/images/cancel-resume-multiple-tasks.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AsyncLetApp/images/cancel-resume-multiple-tasks.gif -------------------------------------------------------------------------------- /AsyncLetApp/images/cancel-task-cascade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AsyncLetApp/images/cancel-task-cascade.png -------------------------------------------------------------------------------- /AsyncLetApp/images/synchronous-download-simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/AsyncLetApp/images/synchronous-download-simulation.png -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4/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 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4/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 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4/CircularSliderWithChatGpt4App.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularSliderWithChatGpt4App.swift 3 | // CircularSliderWithChatGpt4 4 | // 5 | // Created by Eric Callanan on 15/04/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct CircularSliderWithChatGpt4App: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/CircularSliderWithChatGpt4/ThumbView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbView.swift 3 | // CircularSliderWithChatGpt4 4 | // 5 | // Created by Eric Callanan on 15/04/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ThumbView: View { 11 | var body: some View { 12 | ZStack { 13 | // Color(red: 214/255, green: 232/255, blue: 248/255) 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | VStack(spacing: 20) { 17 | CircularSlider5b(size: 200) 18 | HStack(spacing: 20) { 19 | CircularSlider5b(size: 100) 20 | VStack { 21 | CircularSlider5b(size: 50) 22 | HStack { 23 | CircularSlider5b(size: 25) 24 | VStack { 25 | CircularSlider5b(size: 10) 26 | CircularSlider5b(size: 10) 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } 35 | 36 | struct ThumbView_Previews: PreviewProvider { 37 | static var previews: some View { 38 | ThumbView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/images/chatgpt-navigation-multiple-prompts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/CircularSliderWithChatGpt4/images/chatgpt-navigation-multiple-prompts.png -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/images/circular-slider-multiple.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/CircularSliderWithChatGpt4/images/circular-slider-multiple.gif -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/images/circular-slider-not-working.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/CircularSliderWithChatGpt4/images/circular-slider-not-working.gif -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/images/circular-slider-working.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/CircularSliderWithChatGpt4/images/circular-slider-working.gif -------------------------------------------------------------------------------- /CircularSliderWithChatGpt4/images/multiple-circular-sliders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/CircularSliderWithChatGpt4/images/multiple-circular-sliders.png -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp/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 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp/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 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp/Color+Hsb+Rgb.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Color+Hsb+Rgb.swift 3 | // ColorConverterApp 4 | // 5 | // Created by Eric Callanan on 28/04/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | extension Color { 11 | func getHsb() -> (CGFloat, CGFloat, CGFloat, CGFloat) { 12 | var hue: CGFloat = 0.0 13 | var saturation: CGFloat = 0.0 14 | var brightness: CGFloat = 0.0 15 | var alpha: CGFloat = 0.0 16 | 17 | let uiColor = UIColor(self) 18 | uiColor.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) 19 | 20 | return (hue, saturation, brightness, alpha) 21 | } 22 | 23 | func getRgb() -> (CGFloat, CGFloat, CGFloat, CGFloat) { 24 | var red: CGFloat = 0.0 25 | var green: CGFloat = 0.0 26 | var blue: CGFloat = 0.0 27 | var alpha: CGFloat = 0.0 28 | 29 | let uiColor = UIColor(self) 30 | uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha) 31 | 32 | return (red, green, blue, alpha) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp/ColorConverterAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorConverterAppApp.swift 3 | // ColorConverterApp 4 | // 5 | // Created by Eric Callanan on 28/04/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ColorConverterAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ColorConverterApp 4 | // 5 | // Created by Eric Callanan on 28/04/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: DescriptionView(), label: {Text("Color Description")}) 15 | NavigationLink (destination: GetHueView(), label: {Text("UIColor - getHue")}) 16 | NavigationLink (destination: GetRedView(), label: {Text("UIColor - getRed")}) 17 | NavigationLink (destination: HsbExtensionView(), label: {Text("getHSB Extension")}) 18 | NavigationLink (destination: SaturationAndBrightnessView(), label: {Text("Adjust Saturation & Brightness")}) 19 | NavigationLink (destination: ThumbView(), label: {Text("10 ThumbView")}) 20 | } 21 | } 22 | } 23 | } 24 | 25 | struct ContentView_Previews: PreviewProvider { 26 | static var previews: some View { 27 | ContentView() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ColorConverterApp/ColorConverterApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorConverterApp/README.md: -------------------------------------------------------------------------------- 1 | ## ColorConverterApp is a SwiftUI app used to show Color conversion 2 | 3 | 4 |
5 | 6 | HSB (Hue, Saturation, and Brightness) represents color in a more human-understandable 7 | way, which closely mimics how colors are perceived in real life. Defining color using 8 | HSB instead of RGB (Red, Green, and Blue) in App design can result in a more 9 | intuitive design with the creation of harmonious color schemes and color gradients. 10 | This article shows how to convert color to HSB and RGV values using UIColor. 11 | 12 | 13 |
14 | 15 | Full article is 16 | Convert color from RGB to HSB in Swift 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | ### Adjusting Saturation and Brightness 26 | convert-color-thumb 29 | 30 |
31 | 32 | ### Select a Color and see variations in Saturation and Brightness 33 | color-adjust-sat-bright 36 | 37 |
38 | 39 | 40 | 41 | 42 |
43 |
44 |
45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /ColorConverterApp/images/color-adjust-sat-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorConverterApp/images/color-adjust-sat-bright.png -------------------------------------------------------------------------------- /ColorConverterApp/images/convert-color-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorConverterApp/images/convert-color-thumb.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/AngularGradientView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AngularGradientView.swift 3 | // ColorGradientApp 4 | // 5 | // Created by Eric Callanan on 19/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AngularGradientView: View { 11 | @State private var centerPointIndex = 0 12 | 13 | let timer = Timer.publish(every: 2, 14 | on: .main, 15 | in: .common).autoconnect() 16 | 17 | let oneColor = [Color(hue: 0.01, saturation: 0.2, brightness: 0.9), 18 | Color(hue: 0.01, saturation: 1.0, brightness: 0.9)] 19 | 20 | let unitPoints: [UnitPoint] = [ 21 | .init(x:0.2, y: 0.8), 22 | .init(x:0.5, y: 0.2), 23 | .init(x:0.8, y: 0.9)] 24 | 25 | var body: some View { 26 | VStack { 27 | Rectangle() 28 | .fill( 29 | AngularGradient(colors: oneColor, 30 | center: unitPoints[centerPointIndex]) 31 | ) 32 | .animation(Animation.easeInOut.speed(0.2), 33 | value: centerPointIndex) 34 | .frame(width: 400, height: 400) 35 | .onReceive(timer) { input in 36 | centerPointIndex = (centerPointIndex + 1) % unitPoints.count 37 | } 38 | } 39 | .padding() 40 | } 41 | } 42 | 43 | struct AngularGradientView_Previews: PreviewProvider { 44 | static var previews: some View { 45 | AngularGradientView() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/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 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/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 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/castle1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "castle1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/castle1.imageset/castle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/ColorGradientApp/Assets.xcassets/castle1.imageset/castle1.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/castle2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "castle2.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/castle2.imageset/castle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/ColorGradientApp/Assets.xcassets/castle2.imageset/castle2.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountain1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain1.imageset/mountain1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain1.imageset/mountain1.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountain2.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain2.imageset/mountain2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain2.imageset/mountain2.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountain3.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain3.imageset/mountain3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain3.imageset/mountain3.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountain4.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain4.imageset/mountain4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain4.imageset/mountain4.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountain5.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain5.imageset/mountain5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/ColorGradientApp/Assets.xcassets/mountain5.imageset/mountain5.png -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/ColorGradientAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorGradientAppApp.swift 3 | // ColorGradientApp 4 | // 5 | // Created by Eric Callanan on 19/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ColorGradientAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ColorGradientApp 4 | // 5 | // Created by Eric Callanan on 19/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: AngularGradientView(), label: {Text("01 Angular Gradient")}) 15 | NavigationLink (destination: FullBackgroundView(), label: {Text("02 Full background")}) 16 | NavigationLink (destination: PurpleBackgroundView(), label: {Text("03 Purple background")}) 17 | NavigationLink (destination: MaterialBackgroundView(), label: {Text("04 Material background")}) 18 | NavigationLink (destination: ColorBackgroundView(), label: {Text("05 Color background")}) 19 | NavigationLink (destination: MaterialCardsView(), label: {Text("06 Material background with Cards")}) 20 | NavigationLink (destination: ColorWithCardsView(), label: {Text("07 White color background with Cards")}) 21 | } 22 | } 23 | } 24 | } 25 | 26 | struct ContentView_Previews: PreviewProvider { 27 | static var previews: some View { 28 | ContentView() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/FullBackgroundView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FullBackgroundView.swift 3 | // ColorGradientApp 4 | // 5 | // Created by Eric Callanan on 19/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct FullBackgroundView: View { 11 | @State private var centerPointIndex = 0 12 | 13 | let timer = Timer.publish(every: 2, 14 | on: .main, 15 | in: .common).autoconnect() 16 | 17 | let oneColor = [Color(hue: 0.01, saturation: 0.2, brightness: 0.9), 18 | Color(hue: 0.01, saturation: 1.0, brightness: 0.9)] 19 | 20 | let unitPoints: [UnitPoint] = [ 21 | .init(x:0.2, y: 0.8), 22 | .init(x:0.5, y: 0.2), 23 | .init(x:0.8, y: 0.9)] 24 | 25 | var body: some View { 26 | ZStack { 27 | Rectangle() 28 | .fill( 29 | AngularGradient(colors: oneColor, 30 | center: unitPoints[centerPointIndex]) 31 | ) 32 | .animation(Animation.easeInOut.speed(0.20), 33 | value: centerPointIndex) 34 | .onReceive(timer) { input in 35 | centerPointIndex = (centerPointIndex + 1) % unitPoints.count 36 | } 37 | .edgesIgnoringSafeArea(.all) 38 | } 39 | } 40 | } 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | struct FullBackgroundView_Previews: PreviewProvider { 54 | static var previews: some View { 55 | FullBackgroundView() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ColorGradientApp/ColorGradientApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorGradientApp/README.md: -------------------------------------------------------------------------------- 1 | ## ColorGradientApp is a SwiftUI app used to play around with background animation using angular gradient 2 | 3 | 4 |
5 | 6 | Animating the background of an app with a color gradient in SwiftUI can be a great 7 | way to enhance your app. By animating a change in the color gradient of the 8 | background, you can make your app feel more dynamic and engaging. One way to achieve 9 | this effect is by using AngularGradient to keep the background moving. 10 | 11 | 12 |
13 | 14 | Full article is 15 | Animate background with color gradient in SwiftUI 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | ### Use white color with opacity to tone down background animation 25 | color over angular gradient animation 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 |
39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /ColorGradientApp/images/color-over-angular-gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorGradientApp/images/color-over-angular-gradient.png -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/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 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/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 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/BluePencilView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BluePencilView.swift 3 | // ColorPencilsApp 4 | // 5 | // Created by Eric Callanan on 11/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BluePencilView: View { 11 | var body: some View { 12 | VStack { 13 | Text("Blue Pencil") 14 | .font(.largeTitle) 15 | 16 | ColorPencilView1(color: .blue) 17 | .frame(width: 100, height: 400) 18 | } 19 | } 20 | } 21 | 22 | struct ColorPencilView1: View { 23 | var color: Color 24 | 25 | var body: some View { 26 | ZStack { 27 | PencilTipShape() 28 | .fill(color) 29 | PencilTimberShape() 30 | .fill(Color(hue: 0.07, saturation: 0.4, brightness: 0.9)) 31 | PencilBodyShape() 32 | .fill(color) 33 | } 34 | } 35 | } 36 | 37 | struct BluePencilView_Previews: PreviewProvider { 38 | static var previews: some View { 39 | BluePencilView() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/ColorPencilSetView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorPencilSetView.swift 3 | // ColorPencilsApp 4 | // 5 | // Created by Eric Callanan on 11/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ColorPencilSetView: View { 11 | var body: some View { 12 | VStack { 13 | Text("Rainbow Pencil Set") 14 | .font(.largeTitle) 15 | 16 | HStack { 17 | ColorPencilView(color: .red) 18 | ColorPencilView(color: .orange) 19 | ColorPencilView(color: .yellow) 20 | ColorPencilView(color: .green) 21 | ColorPencilView(color: .blue) 22 | ColorPencilView(color: Color(hue: 0.773, saturation: 1.0, brightness: 0.51)) 23 | ColorPencilView(color: Color(hue: 0.771, saturation: 1.0, brightness: 1.00)) 24 | } 25 | .frame(width: 400, height: 300) 26 | } 27 | } 28 | } 29 | 30 | struct ColorPencilSetView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | ColorPencilSetView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/ColorPencilsAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorPencilsAppApp.swift 3 | // ColorPencilsApp 4 | // 5 | // Created by Eric Callanan on 11/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ColorPencilsAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ColorPencilsApp 4 | // 5 | // Created by Eric Callanan on 11/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: GrayPencilView(), label: {Text("Gray Pencil")}) 15 | NavigationLink (destination: BluePencilView(), label: {Text("Blue Pencil")}) 16 | NavigationLink (destination: BlueGradientPencilView(), label: {Text("Color Gradient Pencil")}) 17 | NavigationLink (destination: ColorPencilSetView(), label: {Text("Pencil Set")}) 18 | } 19 | } 20 | } 21 | } 22 | 23 | struct ContentView_Previews: PreviewProvider { 24 | static var previews: some View { 25 | ContentView() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorPencilsApp/ColorPencilsApp/ThumbView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbView.swift 3 | // ColorPencilsApp 4 | // 5 | // Created by Eric Callanan on 11/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ThumbView: View { 11 | var body: some View { 12 | VStack { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | 17 | HStack { 18 | ColorPencilView(color: .red) 19 | ColorPencilView(color: .orange) 20 | ColorPencilView(color: .yellow) 21 | ColorPencilView(color: .green) 22 | ColorPencilView(color: .blue) 23 | ColorPencilView(color: Color(hue: 0.773, saturation: 1.0, brightness: 0.51)) 24 | ColorPencilView(color: Color(hue: 0.771, saturation: 1.0, brightness: 1.00)) 25 | } 26 | .frame(width: 300, height: 200) } 27 | } 28 | } 29 | } 30 | 31 | struct ThumbView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | ThumbView() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ColorPencilsApp/README.md: -------------------------------------------------------------------------------- 1 | ## ColorPencilsApp is a SwiftUI app used to define a Color Pencil 2 | 3 | 4 |
5 | 6 | The color pencil is defined as being composed of three shapes for the pencil tip, the 7 | pencil timber and the pencil body. A 3D effect is added by getting the hue of the 8 | specified color and creating a linear color gradient across the body of the pencil. 9 | 10 | 11 | 12 |
13 | 14 | Full article is 15 | Create a color pencil in SwiftUI 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | ### Rainbow Color Pencil Set 25 | rainbow-color-pencil-set.png 28 | 29 |
30 | 31 | 32 | 33 | 34 |
35 |
36 |
37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /ColorPencilsApp/images/rainbow-color-pencil-set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorPencilsApp/images/rainbow-color-pencil-set.png -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ColorSelectionHsb/ColorSelectionHsb.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb.xcodeproj/xcuserdata/ericcallanan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ColorSelectionHsb.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/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 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/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 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/ColorSelectionHsbApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorSelectionHsbApp.swift 3 | // ColorSelectionHsb 4 | // 5 | // Created by Eric Callanan on 06/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ColorSelectionHsbApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ColorSelectionHsb 4 | // 5 | // Created by Eric Callanan on 06/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationView() { 13 | List { 14 | NavigationLink (destination: RgbColorPaletteView(), label: {Text("RgbColorPaletteView")}) 15 | NavigationLink (destination: HsbColorPaletteView(), label: {Text("HsbColorPaletteView")}) 16 | NavigationLink (destination: ChangeHsbView(), label: {Text("ChangeHsbView")}) 17 | NavigationLink (destination: ColorWheelView(), label: {Text("ColorWheelView")}) 18 | NavigationLink (destination: MatchingColorView(), label: {Text("MatchingColorView")}) 19 | NavigationLink (destination: HueCircularSliderDisplayView(), label: {Text("HueCircularSliderDisplayView")}) 20 | NavigationLink (destination: ThumbView(), label: {Text("ThumbView")}) 21 | } 22 | } 23 | } 24 | } 25 | 26 | struct ContentView_Previews: PreviewProvider { 27 | static var previews: some View { 28 | ContentView() 29 | .previewInterfaceOrientation(.landscapeLeft) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/ThumbView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbView.swift 3 | // ColorSelectionHsb 4 | // 5 | // Created by Eric Callanan on 06/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ThumbView: View { 11 | @State private var hue: Double = 272.0 12 | 13 | var body: some View { 14 | ZStack { 15 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 16 | .edgesIgnoringSafeArea(.all) 17 | 18 | VStack(spacing: 20) { 19 | CircularSliderView(value: $hue, in: 0...360) 20 | .frame(width: 300, height: 300) 21 | RoundedRectangle(cornerRadius: 20) 22 | .fill(Color(hue: self.hue/360.0, saturation: 1.0, brightness: 1.0)) 23 | .frame(width: 300, height: 50, alignment: .center) 24 | } 25 | } 26 | } 27 | } 28 | 29 | 30 | struct ThumbView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | ThumbView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ColorSelectionHsb/ColorSelectionHsb/ViewModels/ColorViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorViewModel.swift 3 | // ColorSelectionHsb 4 | // 5 | // Created by Eric Callanan on 06/11/2022. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | 11 | class ColorViewModel: ObservableObject { 12 | @Published var colorModel: ColorModel 13 | 14 | init() { 15 | self.colorModel = ColorModel() 16 | } 17 | 18 | var selectedColor: Color { 19 | colorModel.color 20 | } 21 | 22 | var monochromaticColors: [Color] { 23 | return colorModel.monochromaticColors 24 | } 25 | 26 | var analogousColors: [Color] { 27 | return colorModel.analogousColors 28 | } 29 | 30 | var complementaryColors: [Color] { 31 | return colorModel.complementaryColors 32 | } 33 | 34 | var triadicColors: [Color] { 35 | return colorModel.triadicColors 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp.xcodeproj/xcuserdata/ericcallanan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | EmployeeNavigationSplitViewApp.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp/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 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "1x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "2x", 16 | "size" : "16x16" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "1x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "2x", 26 | "size" : "32x32" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "2x", 36 | "size" : "128x128" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "1x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "2x", 46 | "size" : "256x256" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "1x", 51 | "size" : "512x512" 52 | }, 53 | { 54 | "idiom" : "mac", 55 | "scale" : "2x", 56 | "size" : "512x512" 57 | } 58 | ], 59 | "info" : { 60 | "author" : "xcode", 61 | "version" : 1 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // EmployeeNavigationSplitViewApp 4 | // 5 | // Created by Eric Callanan on 20/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: TwoColumnView(), label: {Text("01 TwoColumnView")}) 15 | NavigationLink (destination: ThreeColumnView(), label: {Text("02 ThreeColumnView")}) 16 | NavigationLink (destination: ThreeColumnVisibilityView(), label: {Text("03 ThreeColumnVisibilityView")}) 17 | NavigationLink (destination: ThreeColumnDepartmentView(), label: {Text("04 ThreeColumnDepartmentView")}) 18 | NavigationLink (destination: ThreeColumnSingleView(), label: {Text("05 ThreeColumnSingleView")}) 19 | } 20 | .navigationTitle("Title") 21 | .foregroundColor(.red) 22 | } 23 | } 24 | } 25 | 26 | struct ContentView_Previews: PreviewProvider { 27 | static var previews: some View { 28 | ContentView() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EmployeeNavigationSplitViewAppApp.swift 3 | // EmployeeNavigationSplitViewApp 4 | // 5 | // Created by Eric Callanan on 20/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct EmployeeNavigationSplitViewAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EmployeeNavigationSplitViewApp/EmployeeNavigationSplitViewApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp/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 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp/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 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // GameOfLifeApp 4 | // 5 | // Created by Eric Callanan on 20/12/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | @Environment(LifeViewModel.self) private var lifeViewModel 12 | 13 | var body: some View { 14 | NavigationStack() { 15 | List { 16 | NavigationLink (destination: GridLayoutView(), label: {Text("01 Use Grid")}) 17 | NavigationLink (destination: GridFromArrayView(), label: {Text("02 Grid from 2D Array")}) 18 | NavigationLink (destination: CanvasLayoutView(), label: {Text("03 Use Canvas")}) 19 | NavigationLink (destination: CanvasFromArrayView(), label: {Text("04 Canvas from 2D Array")}) 20 | NavigationLink (destination: CanvasFromModelView(), label: {Text("05 Canvas from Model")}) 21 | NavigationLink (destination: GameOfLifeView(gridSize: 20), label: {Text("06 GameOfLifeView")}) 22 | } 23 | } 24 | } 25 | } 26 | 27 | #Preview { 28 | ContentView().environment(LifeViewModel()) 29 | } 30 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp/GameOfLifeAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameOfLifeAppApp.swift 3 | // GameOfLifeApp 4 | // 5 | // Created by Eric Callanan on 20/12/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct GameOfLifeAppApp: App { 12 | 13 | /// The app's state. 14 | @State private var lifeViewModel = LifeViewModel() 15 | 16 | var body: some Scene { 17 | WindowGroup { 18 | ContentView() 19 | .environment(lifeViewModel) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp/LifeViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LifeViewModel.swift 3 | // GameOfLifeApp 4 | // 5 | // Created by Eric Callanan on 20/12/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @Observable class LifeViewModel { 11 | var lifeModel = LifeModel(cells: 10) 12 | private(set) var isRunning: Bool 13 | 14 | init() { 15 | self.isRunning = false 16 | } 17 | 18 | var numberOfCycles: Int { 19 | return lifeModel.numberOfCycles 20 | } 21 | 22 | func reset(gridSize: Int = 10) { 23 | self.isRunning = false 24 | self.lifeModel = LifeModel(cells: gridSize) 25 | } 26 | 27 | func step() { 28 | lifeModel.step() 29 | } 30 | 31 | func setGridSize(cellNumber:Int) { 32 | self.lifeModel = LifeModel(cells: cellNumber) 33 | } 34 | 35 | @MainActor 36 | func performNumberOfCycles(number: Int) async { 37 | self.isRunning = true 38 | for _ in 1...number { 39 | let different = await lifeModel.performStepDelay() 40 | if !different || !self.isRunning { 41 | break 42 | } 43 | } 44 | self.isRunning = false 45 | } 46 | 47 | @MainActor 48 | func stop() async { 49 | self.isRunning = false 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /GameOfLifeApp/GameOfLifeApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /GameOfLifeApp/images/canvas-layout-from-array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/GameOfLifeApp/images/canvas-layout-from-array.png -------------------------------------------------------------------------------- /GameOfLifeApp/images/conways-game-of-life.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/GameOfLifeApp/images/conways-game-of-life.gif -------------------------------------------------------------------------------- /GameOfLifeApp/images/game-of-life-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/GameOfLifeApp/images/game-of-life-view.png -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/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 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/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 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/BlueColorPencilView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlueColorPencilView.swift 3 | // LinearGradientApp 4 | // 5 | // Created by Eric Callanan on 23/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BlueColorPencilView: View { 11 | var body: some View { 12 | VStack { 13 | Text("Blue Pencil") 14 | .font(.largeTitle) 15 | ColorPencilView(color: .blue) 16 | .frame(width: 100, height: 600) 17 | } 18 | } 19 | } 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | struct BlueColorPencilView_Previews: PreviewProvider { 41 | static var previews: some View { 42 | BlueColorPencilView() 43 | } 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // LinearGradientApp 4 | // 5 | // Created by Eric Callanan on 23/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: StartLinearGradientView(), label: {Text("Start Linear Gradient")}) 15 | NavigationLink (destination: StartEndLinearView(), label: {Text("Various Start & End points")}) 16 | NavigationLink (destination: AllStartEndLinearView(), label: {Text("All Start & End points")}) 17 | NavigationLink (destination: PointCoordinateView(), label: {Text("Coordinates for Start & End points")}) 18 | NavigationLink (destination: PencilTipGradientView(), label: {Text("Coordinates on Pencil Tip Gradient")}) 19 | NavigationLink (destination: BlueColorPencilView(), label: {Text("Blue Color Pencil with tip gradient")}) 20 | NavigationLink (destination: PencilSetView(), label: {Text("Color Pencil Set")}) 21 | NavigationLink (destination: ThumbView(), label: {Text("10 ThumbView")}) 22 | } 23 | } 24 | } 25 | } 26 | 27 | struct ContentView_Previews: PreviewProvider { 28 | static var previews: some View { 29 | ContentView() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/LinearGradientAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LinearGradientAppApp.swift 3 | // LinearGradientApp 4 | // 5 | // Created by Eric Callanan on 23/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct LinearGradientAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/PencilSetView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PencilSetView.swift 3 | // LinearGradientApp 4 | // 5 | // Created by Eric Callanan on 23/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | 11 | 12 | 13 | struct PencilSetView: View { 14 | var body: some View { 15 | VStack { 16 | Text("Color Pencils") 17 | .font(.largeTitle) 18 | HStack { 19 | ForEach(AppColors.rainbow, id: \.self) { 20 | ColorPencilView(color: $0) 21 | .frame(width: 50, height: 300) 22 | } 23 | } 24 | Spacer() 25 | } 26 | } 27 | } 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | struct PencilSetView_Previews: PreviewProvider { 36 | static var previews: some View { 37 | PencilSetView() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LinearGradientApp/LinearGradientApp/ThumbView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbView.swift 3 | // LinearGradientApp 4 | // 5 | // Created by Eric Callanan on 23/05/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ThumbView: View { 11 | var body: some View { 12 | VStack { 13 | ZStack { 14 | // Color(red: 214/255, green: 232/255, blue: 248/255) 15 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 16 | .edgesIgnoringSafeArea(.all) 17 | VStack { 18 | RoundedRectangle(cornerRadius: 20) 19 | .fill( 20 | LinearGradient(colors: AppColors.rainbow, 21 | startPoint: .topTrailing, 22 | endPoint: .bottomLeading) 23 | ) 24 | .frame(width: 200, height: 200) 25 | } 26 | .padding() 27 | } 28 | } 29 | } 30 | } 31 | struct ThumbView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | ThumbView() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LinearGradientApp/images/all-linear-gradient-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/LinearGradientApp/images/all-linear-gradient-options.png -------------------------------------------------------------------------------- /LinearGradientApp/images/color-pencil-set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/LinearGradientApp/images/color-pencil-set.png -------------------------------------------------------------------------------- /LinearGradientApp/images/linear-gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/LinearGradientApp/images/linear-gradient.png -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/MathewEffectApp/MatthewEffectApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp.xcodeproj/xcuserdata/ericcallanan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MathewEffectApp.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | MatthewEffectApp.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/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 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/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 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/MatthewEffectAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MatthewEffectAppApp.swift 3 | // MathewEffectApp 4 | // 5 | // Created by Eric Callanan on 27/09/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct MatthewEffectAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/Views/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // MathewEffectApp 4 | // 5 | // Created by Eric Callanan on 27/09/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationView() { 13 | List { 14 | NavigationLink (destination: ScenarioOneView(), label: {Text("01 ScenarioOneView")}) 15 | NavigationLink (destination: ScenarioTwoView(), label: {Text("02 ScenarioTwoView")}) 16 | NavigationLink (destination: ScenarioThreeView(), label: {Text("03 ScenarioThreeView")}) 17 | NavigationLink (destination: ScenarioFourView(), label: {Text("04 ScenarioFourView")}) 18 | } 19 | .navigationTitle("Matthews Effect") 20 | } 21 | } 22 | } 23 | 24 | struct ContentView_Previews: PreviewProvider { 25 | static var previews: some View { 26 | ContentView() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/Views/ScenarioFourView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScenarioFourView.swift 3 | // MathewEffectApp 4 | // 5 | // Created by Eric Callanan on 27/09/2022. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct ScenarioFourView: View { 12 | @ObservedObject var mathewGame = MatthewViewModel(allowAgentsWithZero: false) 13 | 14 | var body: some View { 15 | ZStack { 16 | Color(hue: 0.58, saturation: 0.07, brightness: 1.0) 17 | .edgesIgnoringSafeArea(.all) 18 | 19 | VStack { 20 | CoinBarChartView(mathewGame: mathewGame, 21 | chartTitle: "4: Agents with zero coin are out", 22 | displayFailedTransactionCount: false) 23 | 24 | SettingsView(transferAmount: "1", 25 | allowPlayWithZero: mathewGame.allowAgentsWithZero, 26 | allowNegative: mathewGame.allowNegative) 27 | 28 | RunTransactionsView(mathewGame: mathewGame, 29 | numOfTransactions: 10, 30 | transferAmount: 1) 31 | 32 | Spacer() 33 | } 34 | } 35 | } 36 | } 37 | 38 | struct ScenarioFourView_Previews: PreviewProvider { 39 | static var previews: some View { 40 | ScenarioFourView() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/Views/ScenarioOneView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScenarioOneView.swift 3 | // MathewEffectApp 4 | // 5 | // Created by Eric Callanan on 27/09/2022. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | 12 | struct ScenarioOneView: View { 13 | @ObservedObject var mathewGame = MatthewViewModel() 14 | 15 | var body: some View { 16 | ZStack { 17 | Color(hue: 0.58, saturation: 0.07, brightness: 1.0) 18 | .edgesIgnoringSafeArea(.all) 19 | 20 | VStack { 21 | CoinBarChartView(mathewGame: mathewGame, 22 | chartTitle: "1: Exchange of random amounts") 23 | 24 | SettingsView(transferAmount: "random 1 to \(Config.totalCoin)", 25 | allowPlayWithZero: mathewGame.allowAgentsWithZero, 26 | allowNegative: mathewGame.allowNegative) 27 | 28 | RunTransactionsView(mathewGame: mathewGame, 29 | numOfTransactions: 10) 30 | 31 | Spacer() 32 | } 33 | } 34 | } 35 | } 36 | 37 | 38 | struct ScenarioOneView_Previews: PreviewProvider { 39 | static var previews: some View { 40 | ScenarioOneView() 41 | } 42 | } 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/Views/ScenarioThreeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScenarioThreeView.swift 3 | // MathewEffectApp 4 | // 5 | // Created by Eric Callanan on 27/09/2022. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct ScenarioThreeView: View { 12 | @ObservedObject var mathewGame = MatthewViewModel(allowNegativeCount: true) 13 | 14 | var body: some View { 15 | ZStack { 16 | Color(hue: 0.58, saturation: 0.07, brightness: 1.0) 17 | .edgesIgnoringSafeArea(.all) 18 | 19 | VStack { 20 | CoinBarChartView(mathewGame: mathewGame, 21 | chartTitle: "3: Allow negative coin count", 22 | displayNegative: true) 23 | 24 | SettingsView(transferAmount: "1", 25 | allowPlayWithZero: mathewGame.allowAgentsWithZero, 26 | allowNegative: mathewGame.allowNegative) 27 | 28 | 29 | RunTransactionsView(mathewGame: mathewGame, 30 | numOfTransactions: 10, 31 | transferAmount: 1) 32 | 33 | Spacer() 34 | } 35 | } 36 | } 37 | } 38 | 39 | struct ScenarioThreeView_Previews: PreviewProvider { 40 | static var previews: some View { 41 | ScenarioThreeView() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MathewEffectApp/MatthewEffectApp/Views/ScenarioTwoView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScenarioTwoView.swift 3 | // MathewEffectApp 4 | // 5 | // Created by Eric Callanan on 27/09/2022. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct ScenarioTwoView: View { 12 | @ObservedObject var mathewGame = MatthewViewModel() 13 | 14 | var body: some View { 15 | ZStack { 16 | Color(hue: 0.58, saturation: 0.07, brightness: 1.0) 17 | .edgesIgnoringSafeArea(.all) 18 | 19 | VStack { 20 | CoinBarChartView(mathewGame: mathewGame, 21 | chartTitle: "2: Exchange of 1 coin") 22 | 23 | SettingsView(transferAmount: "1", 24 | allowPlayWithZero: mathewGame.allowAgentsWithZero, 25 | allowNegative: mathewGame.allowNegative) 26 | 27 | 28 | RunTransactionsView(mathewGame: mathewGame, 29 | numOfTransactions: 10, 30 | transferAmount: 1) 31 | 32 | Spacer() 33 | } 34 | } 35 | } 36 | } 37 | 38 | 39 | struct ScenarioTwoView_Previews: PreviewProvider { 40 | static var previews: some View { 41 | ScenarioTwoView() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/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 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/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 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/BarAndPieChartView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BarAndPieChartView.swift 3 | // PieChartApp 4 | // 5 | // Created by Eric Callanan on 15/10/2023. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct BarAndPieChartView: View { 12 | var body: some View { 13 | VStack { 14 | GroupBox ( "Bar Chart - 2022 Donations and legacies (€ million)") { 15 | Chart(donationsIncomeData) { 16 | BarMark( 17 | x: .value("Amount", $0.amount), 18 | stacking: .normalized 19 | ) 20 | .foregroundStyle(by: .value("category", $0.category)) 21 | } 22 | } 23 | .frame(height: 200) 24 | 25 | GroupBox ( "Pie Chart - 2022 Donations and legacies (€ million)") { 26 | Chart(donationsIncomeData) { 27 | SectorMark( 28 | angle: .value("Amount", $0.amount) 29 | ) 30 | .foregroundStyle(by: .value("category", $0.category)) 31 | } 32 | } 33 | .frame(height: 500) 34 | 35 | Spacer() 36 | } 37 | .padding() 38 | } 39 | } 40 | 41 | #Preview { 42 | BarAndPieChartView() 43 | } 44 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/BarChartView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BarChartView.swift 3 | // PieChartApp 4 | // 5 | // Created by Eric Callanan on 15/10/2023. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct BarChartView: View { 12 | var body: some View { 13 | VStack { 14 | GroupBox ( "Bar Chart - 2022 Income (€ million)") { 15 | Chart(totalIncomeData) { 16 | BarMark( 17 | x: .value("Category", $0.category), 18 | y: .value("Amount", $0.amount) 19 | ) 20 | } 21 | } 22 | .frame(height: 300) 23 | 24 | GroupBox ("2022 Donations and legacies (€ million)") { 25 | Chart(donationsIncomeData) { 26 | BarMark( 27 | x: .value("Category", $0.category), 28 | y: .value("Amount", $0.amount) 29 | ) 30 | } 31 | } 32 | .frame(height: 300) 33 | 34 | 35 | Spacer() 36 | } 37 | .padding() 38 | } 39 | } 40 | 41 | 42 | #Preview { 43 | BarChartView() 44 | } 45 | 46 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // PieChartApp 4 | // 5 | // Created by Eric Callanan on 15/10/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: BarChartView(), label: {Text("01 Bar Chart")}) 15 | NavigationLink (destination: BarAndPieChartView(), label: {Text("02 Bar and Pie Chart")}) 16 | NavigationLink (destination: RoundedSectorSpaceView(), label: {Text("03 Rounded Sectors with spaces")}) 17 | NavigationLink (destination: DonutChartView(), label: {Text("04 Donut Chart")}) 18 | NavigationLink (destination: PieChartColorsView(), label: {Text("05 Pie Chart with custom colors")}) 19 | NavigationLink (destination: InteractiveDonutView(), label: {Text("06 Interactive Donut Chart")}) 20 | NavigationLink (destination: DonutChartSortedView(), label: {Text("07 Donut Chart Sorted Data")}) 21 | NavigationLink (destination: DonutWithLabelsView(), label: {Text("08 Donut with Labels")}) 22 | } 23 | } 24 | } 25 | } 26 | 27 | #Preview { 28 | ContentView() 29 | } 30 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/DonutChartView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DonutChartView.swift 3 | // PieChartApp 4 | // 5 | // Created by Eric Callanan on 15/10/2023. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct DonutChartView: View { 12 | var body: some View { 13 | VStack { 14 | GroupBox ("2022 Donations and Legacies (€ million)") { 15 | Chart(donationsIncomeData) { 16 | SectorMark( 17 | angle: .value("Amount", $0.amount), 18 | innerRadius: .ratio(0.6), 19 | angularInset: 3.0 20 | ) 21 | .cornerRadius(6.0) 22 | .foregroundStyle(by: .value("category", $0.category)) 23 | } 24 | } 25 | .frame(height: 500) 26 | 27 | Spacer() 28 | } 29 | .padding() 30 | } 31 | } 32 | 33 | #Preview { 34 | DonutChartView() 35 | } 36 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/PieChartAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PieChartAppApp.swift 3 | // PieChartApp 4 | // 5 | // Created by Eric Callanan on 15/10/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct PieChartAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/PieChartColorsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PieChartColorsView.swift 3 | // PieChartApp 4 | // 5 | // Created by Eric Callanan on 15/10/2023. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct PieChartColorsView: View { 12 | var body: some View { 13 | VStack { 14 | GroupBox ( "2022 Donations and Legacies (€ million)") { 15 | Chart(donationsIncomeData) { 16 | SectorMark( 17 | angle: .value("Amount", $0.amount), 18 | angularInset: 3.0 19 | ) 20 | .cornerRadius(6.0) 21 | .foregroundStyle(by: .value("category", $0.category)) 22 | } 23 | // Set color for each data in the chart 24 | .chartForegroundStyleScale( 25 | domain: donationsIncomeData.map { $0.category }, 26 | range: chartColors 27 | ) 28 | 29 | // Position the Legend 30 | .chartLegend(position: .top, alignment: .center) 31 | } 32 | .frame(height: 500) 33 | 34 | Spacer() 35 | } 36 | .padding() 37 | } 38 | } 39 | 40 | #Preview { 41 | PieChartColorsView() 42 | } 43 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PieChartApp/PieChartApp/RoundedSectorSpaceView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RoundedSectorSpaceView.swift 3 | // PieChartApp 4 | // 5 | // Created by Eric Callanan on 15/10/2023. 6 | // 7 | 8 | import SwiftUI 9 | import Charts 10 | 11 | struct RoundedSectorSpaceView: View { 12 | var body: some View { 13 | VStack { 14 | GroupBox ( "2022 Donations and Legacies (€ million)") { 15 | Chart(donationsIncomeData) { 16 | SectorMark( 17 | angle: .value("Amount", $0.amount), 18 | angularInset: 3.0 19 | ) 20 | .cornerRadius(6.0) 21 | .foregroundStyle(by: .value("category", $0.category)) 22 | } 23 | } 24 | .frame(height: 500) 25 | 26 | Spacer() 27 | } 28 | .padding() 29 | } 30 | } 31 | 32 | #Preview { 33 | RoundedSectorSpaceView() 34 | } 35 | -------------------------------------------------------------------------------- /PieChartApp/images/donut-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/PieChartApp/images/donut-chart.png -------------------------------------------------------------------------------- /PieChartApp/images/donut-interactive-chart-labels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/PieChartApp/images/donut-interactive-chart-labels.png -------------------------------------------------------------------------------- /PieChartApp/images/interactive-donut-chart-with-labels.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/PieChartApp/images/interactive-donut-chart-with-labels.gif -------------------------------------------------------------------------------- /PieChartApp/images/pie-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/PieChartApp/images/pie-chart.png -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/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 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/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 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // RadialGradientApp 4 | // 5 | // Created by Eric Callanan on 08/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: StartRadialGradientView(), label: {Text("01 Start Radial Gradient")}) 15 | NavigationLink (destination: CenterOptionsView(), label: {Text("02 All Center Options")}) 16 | NavigationLink (destination: AnimateCenterView(), label: {Text("03 Animate move center point")}) 17 | NavigationLink (destination: StartEndRadiusView(), label: {Text("04 Start & end radius settings")}) 18 | NavigationLink (destination: AnimateRadiiView(), label: {Text("05 Animate start & end radii")}) 19 | NavigationLink (destination: AnimateCenterRadiiView(), label: {Text("06 Animate center, start & end radii")}) 20 | NavigationLink (destination: HypnoticView(), label: {Text("07 Hypnotic")}) 21 | NavigationLink (destination: RainbowView(), label: {Text("08 Rainbow")}) 22 | } 23 | } 24 | } 25 | } 26 | 27 | struct ContentView_Previews: PreviewProvider { 28 | static var previews: some View { 29 | ContentView() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/HypnoticView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HypnoticView.swift 3 | // RadialGradientApp 4 | // 5 | // Created by Eric Callanan on 08/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct HypnoticView: View { 11 | @State private var colorIndex = 0 12 | @State private var colors = AppColors.rainbow 13 | 14 | let timer = Timer.publish(every: 0.12, 15 | on: .main, 16 | in: .common).autoconnect() 17 | func colorList() -> [Color] { 18 | colorIndex += 1 19 | return AppColors.rainbow.indices.map { AppColors.rainbow.wrap(index: (colorIndex - $0)) } 20 | } 21 | 22 | var body: some View { 23 | VStack(alignment: .trailing) { 24 | 25 | Circle() 26 | .fill( 27 | RadialGradient(colors: colors, 28 | center: .center, 29 | startRadius: 10, 30 | endRadius: 200) 31 | ) 32 | .animation(Animation.easeInOut.speed(0.12), 33 | value: colorIndex) 34 | .frame(width: 400, height: 400) 35 | .onReceive(timer) { _ in 36 | colors = colorList() 37 | } 38 | } 39 | } 40 | } 41 | 42 | struct HypnoticView_Previews: PreviewProvider { 43 | static var previews: some View { 44 | HypnoticView() 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/RadialGradientAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RadialGradientAppApp.swift 3 | // RadialGradientApp 4 | // 5 | // Created by Eric Callanan on 08/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct RadialGradientAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/RainbowView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RainbowView.swift 3 | // RadialGradientApp 4 | // 5 | // Created by Eric Callanan on 08/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct RainbowView: View { 11 | var body: some View { 12 | VStack(spacing: 100) { 13 | RoundedRectangle(cornerRadius: 20) 14 | .fill( 15 | RadialGradient(colors: AppColors.rainbowClear.reversed(), 16 | center: .bottom, 17 | startRadius: 150, 18 | endRadius: 200) 19 | ) 20 | .frame(width: 400, height: 200) 21 | 22 | 23 | RoundedRectangle(cornerRadius: 20) 24 | .fill( 25 | RadialGradient(colors: AppColors.rainbowClear.reversed(), 26 | center: UnitPoint(x: 0.5, y: 1.6), 27 | startRadius: 150, 28 | endRadius: 300) 29 | ) 30 | .frame(width: 400, height: 200) 31 | } 32 | } 33 | } 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | struct RainbowView_Previews: PreviewProvider { 53 | static var previews: some View { 54 | RainbowView() 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /RadialGradientApp/RadialGradientApp/ThumbView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbView.swift 3 | // RadialGradientApp 4 | // 5 | // Created by Eric Callanan on 08/07/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ThumbView: View { 11 | var body: some View { 12 | VStack { 13 | ZStack { 14 | // Color(red: 214/255, green: 232/255, blue: 248/255) 15 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 16 | .edgesIgnoringSafeArea(.all) 17 | 18 | VStack(alignment: .trailing) { 19 | Circle() 20 | .fill( 21 | RadialGradient(colors: AppColors.rainbow, 22 | center: .center, 23 | startRadius: 20, 24 | endRadius: 195) 25 | ) 26 | .frame(width: 400, height: 400) 27 | } 28 | 29 | .padding() 30 | } 31 | } 32 | } 33 | } 34 | 35 | struct ThumbView_Previews: PreviewProvider { 36 | static var previews: some View { 37 | ThumbView() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /RadialGradientApp/images/change-center-start-end-radii.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/RadialGradientApp/images/change-center-start-end-radii.gif -------------------------------------------------------------------------------- /RadialGradientApp/images/radial-gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/RadialGradientApp/images/radial-gradient.png -------------------------------------------------------------------------------- /RadialGradientApp/images/radial-iterating-through-colors.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/RadialGradientApp/images/radial-iterating-through-colors.gif -------------------------------------------------------------------------------- /RadialGradientApp/images/rainbow-with-radialgradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/RadialGradientApp/images/rainbow-with-radialgradient.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Animal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Animal.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 15/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Animal: Identifiable { 11 | let id = UUID() 12 | let name: String 13 | 14 | init(num: Int) { 15 | self.name = "animal-\( String(repeating: "0", count: num < 10 ? 1 : 0) )\(num)" 16 | } 17 | } 18 | 19 | 20 | struct Animals { 21 | var animalList: [Animal] 22 | 23 | init() { 24 | animalList = [] 25 | for i in 1...25 { 26 | animalList.append(Animal(num: i)) 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/AnimalCardView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimalCardView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AnimalCardView: View { 11 | var animal: Animal 12 | 13 | var body: some View { 14 | ZStack { 15 | RoundedRectangle(cornerRadius: 40) 16 | .fill(.yellow.opacity(0.3)) 17 | .frame(width: 320, height: 240) 18 | .shadow(color: .black, radius: 7, x: 8, y: 10) 19 | Image(animal.name) 20 | .resizable() 21 | .scaledToFit() 22 | .frame(width: 320, height: 240) 23 | .clipShape(RoundedRectangle(cornerRadius: 40)) 24 | .overlay(RoundedRectangle(cornerRadius: 40) 25 | .strokeBorder(Color.yellow.opacity(0.4), lineWidth: 6)) 26 | } 27 | } 28 | } 29 | 30 | #Preview { 31 | AnimalCardView(animal: Animal(num: 25)) 32 | } 33 | 34 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/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 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "1x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "2x", 16 | "size" : "16x16" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "1x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "2x", 26 | "size" : "32x32" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "2x", 36 | "size" : "128x128" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "1x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "2x", 46 | "size" : "256x256" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "1x", 51 | "size" : "512x512" 52 | }, 53 | { 54 | "idiom" : "mac", 55 | "scale" : "2x", 56 | "size" : "512x512" 57 | } 58 | ], 59 | "info" : { 60 | "author" : "xcode", 61 | "version" : 1 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-01.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-01.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-01.imageset/animal-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-01.imageset/animal-01.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-02.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-02.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-02.imageset/animal-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-02.imageset/animal-02.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-03.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-03.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-03.imageset/animal-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-03.imageset/animal-03.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-04.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-04.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-04.imageset/animal-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-04.imageset/animal-04.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-05.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-05.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-05.imageset/animal-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-05.imageset/animal-05.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-06.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-06.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-06.imageset/animal-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-06.imageset/animal-06.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-07.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-07.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-07.imageset/animal-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-07.imageset/animal-07.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-08.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-08.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-08.imageset/animal-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-08.imageset/animal-08.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-09.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-09.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-09.imageset/animal-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-09.imageset/animal-09.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-10.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-10.imageset/animal-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-10.imageset/animal-10.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-11.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-11.imageset/animal-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-11.imageset/animal-11.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-12.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-12.imageset/animal-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-12.imageset/animal-12.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-13.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-13.imageset/animal-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-13.imageset/animal-13.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-14.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-14.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-14.imageset/animal-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-14.imageset/animal-14.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-15.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-15.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-15.imageset/animal-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-15.imageset/animal-15.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-16.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-16.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-16.imageset/animal-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-16.imageset/animal-16.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-17.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-17.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-17.imageset/animal-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-17.imageset/animal-17.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-18.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-18.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-18.imageset/animal-18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-18.imageset/animal-18.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-19.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-19.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-19.imageset/animal-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-19.imageset/animal-19.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-20.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-20.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-20.imageset/animal-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-20.imageset/animal-20.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-21.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-21.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-21.imageset/animal-21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-21.imageset/animal-21.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-22.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-22.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-22.imageset/animal-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-22.imageset/animal-22.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-23.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-23.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-23.imageset/animal-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-23.imageset/animal-23.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-24.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-24.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-24.imageset/animal-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-24.imageset/animal-24.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-25.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "animal-25.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-25.imageset/animal-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animal-25.imageset/animal-25.png -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Assets.xcassets/animals/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: NoTransitionView(), label: {Text("01 No Scroll Transition")}) 15 | NavigationLink (destination: ScaleTransitionView(), label: {Text("02 Scale Transition")}) 16 | NavigationLink (destination: OpacityTransitionView(), label: {Text("03 Opacity Transition")}) 17 | NavigationLink (destination: OffsetTransitionView(), label: {Text("04 Offset Transition")}) 18 | NavigationLink (destination: ScaleOpacityView(), label: {Text("05 Scale and Opacity")}) 19 | NavigationLink (destination: ViewAlignedView(), label: {Text("06 View Aligned")}) 20 | NavigationLink (destination: ScaleOpacityRotationView(), label: {Text("07 Sale, Opacity and Rotation")}) 21 | NavigationLink (destination: PerspectiveView(), label: {Text("08 Perspective")}) 22 | } 23 | } 24 | } 25 | } 26 | 27 | #Preview { 28 | ContentView() 29 | } 30 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/NoTransitionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NoTransitionView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct NoTransitionView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "No Transition") 16 | 17 | ScrollView { 18 | LazyVStack { 19 | ForEach (animals.animalList) { animal in 20 | AnimalCardView(animal: animal) 21 | } 22 | } 23 | } 24 | } 25 | } 26 | } 27 | 28 | #Preview { 29 | NoTransitionView() 30 | } 31 | 32 | 33 | struct HeaderView: View { 34 | var heading: String 35 | 36 | var body: some View { 37 | Text(heading) 38 | .font(.title) 39 | .fontWeight(.bold) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/OffsetTransitionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OffsetTransitionView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct OffsetTransitionView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "Offset Transition") 16 | 17 | ScrollView { 18 | LazyVStack { 19 | ForEach (animals.animalList) { animal in 20 | AnimalCardView(animal: animal) 21 | .scrollTransition { content, phase in 22 | content.offset(x: phase.isIdentity ? 0 : 400) 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } 30 | 31 | #Preview { 32 | OffsetTransitionView() 33 | } 34 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/OpacityTransitionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OpacityTransitionView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct OpacityTransitionView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "Opacity Transition") 16 | 17 | ScrollView { 18 | LazyVStack { 19 | ForEach (animals.animalList) { animal in 20 | AnimalCardView(animal: animal) 21 | .scrollTransition { content, phase in 22 | content.opacity(phase.isIdentity ? 1 : 0) 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } 30 | 31 | #Preview { 32 | OpacityTransitionView() 33 | } 34 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/PerspectiveView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PerspectiveView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PerspectiveView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "Perspective") 16 | 17 | ScrollView { 18 | LazyVStack { 19 | ForEach (animals.animalList) { animal in 20 | AnimalCardView(animal: animal) 21 | .scrollTransition(.interactive) { content, phase in content 22 | .scaleEffect(phase.isIdentity ? 1.0 : 0.7) 23 | .rotation3DEffect( 24 | Angle.degrees(phase.value * -70.0), 25 | axis: (x: 1.0, y: 0.0, z: 0.0), 26 | perspective: 0.01) 27 | } 28 | } 29 | } 30 | } 31 | 32 | } 33 | } 34 | } 35 | 36 | #Preview { 37 | PerspectiveView() 38 | } 39 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ScaleOpacityRotationView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScaleOpacityRotationView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ScaleOpacityRotationView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "Scale, Opacity,") 16 | HeaderView(heading: "Rotation and Offset") 17 | 18 | ScrollView { 19 | LazyVStack { 20 | ForEach (animals.animalList) { animal in 21 | AnimalCardView(animal: animal) 22 | .scrollTransition(.interactive) { content, phase in 23 | content 24 | .scaleEffect(phase.isIdentity ? 1.0 : 0.2) 25 | .opacity(phase.isIdentity ? 1 : 0.5) 26 | .rotation3DEffect( 27 | Angle.degrees(phase.isIdentity ? 0: 90), 28 | axis: (x: 0.5, y: 0.0, z: 0.1)) 29 | .offset(x: phase.value * -200) 30 | } 31 | } 32 | } 33 | .scrollTargetLayout() 34 | } 35 | .scrollTargetBehavior(.viewAligned) 36 | } 37 | } 38 | } 39 | 40 | #Preview { 41 | ScaleOpacityRotationView() 42 | } 43 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ScaleOpacityView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScaleOpacityView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ScaleOpacityView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "Scale & Opacity Transition") 16 | 17 | ScrollView { 18 | LazyVStack { 19 | ForEach (animals.animalList) { animal in 20 | AnimalCardView(animal: animal) 21 | .scrollTransition { content, phase in 22 | content 23 | .scaleEffect(phase.isIdentity ? 1 : 0.3) 24 | .opacity(phase.isIdentity ? 1 : 0.3) 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | } 32 | 33 | #Preview { 34 | ScaleOpacityView() 35 | } 36 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ScaleTransitionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScaleTransitionView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ScaleTransitionView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "Scale Transition") 16 | 17 | ScrollView { 18 | LazyVStack { 19 | ForEach (animals.animalList) { animal in 20 | AnimalCardView(animal: animal) 21 | .scrollTransition { content, phase in 22 | content.scaleEffect(phase.isIdentity ? 1 : 0.6) 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } 30 | 31 | #Preview { 32 | ScaleTransitionView() 33 | } 34 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ScrollEffectApp.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ScrollEffectAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollEffectAppApp.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ScrollEffectAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ThumbView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ThumbView: View { 11 | var body: some View { 12 | VStack { 13 | ZStack { 14 | Color(hue: 0.58, saturation: 0.17, brightness: 1.0) 15 | .edgesIgnoringSafeArea(.all) 16 | VStack { 17 | AnimalCardView(animal: Animal(num: 11)) 18 | .offset(x:80) 19 | .scaleEffect(0.8) 20 | AnimalCardView(animal: Animal(num: 6)) 21 | .offset(x: -100) 22 | AnimalCardView(animal: Animal(num: 19)) 23 | .offset(x: -100) 24 | AnimalCardView(animal: Animal(num: 9)) 25 | .offset(x:80, y: 30) 26 | .opacity(0.4) 27 | } 28 | .scaleEffect(0.5) 29 | } 30 | } 31 | } 32 | } 33 | 34 | #Preview { 35 | ThumbView() 36 | } 37 | -------------------------------------------------------------------------------- /ScrollEffectApp/ScrollEffectApp/ViewAlignedView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewAlignedView.swift 3 | // ScrollEffectApp 4 | // 5 | // Created by Eric Callanan on 03/01/2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ViewAlignedView: View { 11 | let animals = Animals() 12 | 13 | var body: some View { 14 | VStack { 15 | HeaderView(heading: "Scale & Opacity Transition") 16 | Text("viewAligned") 17 | 18 | ScrollView { 19 | LazyVStack { 20 | ForEach (animals.animalList) { animal in 21 | AnimalCardView(animal: animal) 22 | .scrollTransition { content, phase in 23 | content 24 | .scaleEffect(phase.isIdentity ? 1 : 0.3) 25 | .opacity(phase.isIdentity ? 1 : 0.3) 26 | } 27 | } 28 | } 29 | .scrollTargetLayout() 30 | } 31 | .scrollTargetBehavior(.viewAligned) 32 | } 33 | } 34 | } 35 | 36 | #Preview { 37 | ViewAlignedView() 38 | } 39 | -------------------------------------------------------------------------------- /ScrollEffectApp/images/card-scale-opacity-rotation-animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/images/card-scale-opacity-rotation-animation.gif -------------------------------------------------------------------------------- /ScrollEffectApp/images/cards-no-transition-animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/images/cards-no-transition-animation.gif -------------------------------------------------------------------------------- /ScrollEffectApp/images/cards-scale-opacity-animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/images/cards-scale-opacity-animation.gif -------------------------------------------------------------------------------- /ScrollEffectApp/images/cards-scale-opacity-transition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollEffectApp/images/cards-scale-opacity-transition.png -------------------------------------------------------------------------------- /ScrollingChartsApp/README.md: -------------------------------------------------------------------------------- 1 | ## Add horizontal scrolling to Swift Charts 2 | 3 | 4 | 5 | Apple introduced SwiftUI Charts at WWWDC 2022, which makes it incredibly easy to 6 | create charts within SwiftUI views. The default chart presents the entire data in the 7 | chart plot regardless of how much data is available. It can be beneficial to show 8 | more details on a chart and add the ability to scroll through the chart. 9 | 10 | 11 | 12 | Horizontal scrolling to Swift Bar Chart 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/ScrollingChartsApp/ScrollingChartsApp.xcodeproj/project.xcworkspace/xcuserdata/ericcallanan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp.xcodeproj/xcuserdata/ericcallanan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ScrollingChartsApp.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/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 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/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 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ScrollingChartsApp 4 | // 5 | // Created by Eric Callanan on 28/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | NavigationStack() { 13 | List { 14 | NavigationLink (destination: WeightChartView1(), label: {Text("Line Chart")}) 15 | NavigationLink (destination: WeightChartView2(), label: {Text("Bar Chart")}) 16 | NavigationLink (destination: WeightChartView3(), label: {Text("Line Chart with Scroll")}) 17 | NavigationLink (destination: WeightChartView4(), label: {Text("Bar Chart with Scroll")}) 18 | } 19 | } 20 | } 21 | } 22 | 23 | struct ContentView_Previews: PreviewProvider { 24 | static var previews: some View { 25 | ContentView() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/Date+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Date+Extensions.swift 3 | // ScrollingChartsApp 4 | // 5 | // Created by Eric Callanan on 28/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | extension Date { 11 | func toString() -> String { 12 | let dateFormatter = DateFormatter() 13 | dateFormatter.dateStyle = .long 14 | dateFormatter.timeStyle = .none 15 | dateFormatter.locale = Locale(identifier: "en_US") 16 | return dateFormatter.string(from: self) 17 | } 18 | 19 | func isFirstOfMonth() -> Bool { 20 | let components = Calendar.current.dateComponents([.day], from: self) 21 | return components.day == 1 22 | } 23 | 24 | func monthName() -> String { 25 | let dateFormatter = DateFormatter() 26 | dateFormatter.dateFormat = "MMMM" 27 | dateFormatter.locale = Locale(identifier: "en_US") 28 | return dateFormatter.string(from: self) 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/ScrollingChartsAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollingChartsAppApp.swift 3 | // ScrollingChartsApp 4 | // 5 | // Created by Eric Callanan on 28/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ScrollingChartsAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/Styles.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Styles.swift 3 | // ScrollingChartsApp 4 | // 5 | // Created by Eric Callanan on 28/11/2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct YellowGroupBoxStyle: GroupBoxStyle { 11 | func makeBody(configuration: Configuration) -> some View { 12 | configuration.content 13 | .padding(.top, 30) 14 | .padding(20) 15 | .background(Color(hue: 0.10, saturation: 0.10, brightness: 0.98)) 16 | .cornerRadius(20) 17 | .overlay( 18 | configuration.label.padding(10), 19 | alignment: .topLeading 20 | ) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ScrollingChartsApp/ScrollingChartsApp/WeightViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeightViewModel.swift 3 | // ScrollingChartsApp 4 | // 5 | // Created by Eric Callanan on 28/11/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | class WeightViewModel: ObservableObject { 11 | @Published private var weightModel = WeightData() 12 | 13 | init() { 14 | weightModel.createWeightData(days: 100) 15 | } 16 | 17 | var allWeights: [Weight]? { 18 | weightModel.allWeights 19 | } 20 | 21 | func generateWeightData(numberOfDays: Int) { 22 | weightModel.createWeightData(days: numberOfDays) 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/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 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/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 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/EditableTaskView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EditableTaskView.swift 3 | // TasksAppWithChatGpt 4 | // 5 | // Created by Eric Callanan on 19/03/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct EditableTaskView: View { 11 | @Binding var task: Task 12 | 13 | var body: some View { 14 | VStack(alignment: .leading) { 15 | TextField("Title", text: $task.title) 16 | if let dueDate = task.dueDate { 17 | DatePicker("Due date", selection: Binding( 18 | get: { dueDate }, 19 | set: { newValue in self.task.dueDate = newValue } // use the binding directly 20 | ), displayedComponents: .date) 21 | } 22 | Picker("Task Status", selection: $task.status) { 23 | ForEach(TaskStatus.allCases, id: \.self) { status in 24 | Text(status.rawValue).tag(status) 25 | } 26 | } 27 | .pickerStyle(SegmentedPickerStyle()) 28 | } 29 | .foregroundColor(task.completed ? .gray : .primary) 30 | .opacity(task.completed ? 0.5 : 1) 31 | } 32 | } 33 | 34 | struct EditableTaskView_Previews: PreviewProvider { 35 | static var previews: some View { 36 | EditableTaskView(task: .constant( 37 | Task(title: "task 42", 38 | dueDate: Date(), 39 | status: .inProgress) 40 | )) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/TaskListViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TaskListViewModel.swift 3 | // TasksAppWithChatGpt 4 | // 5 | // Created by Eric Callanan on 17/03/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | class TaskListViewModel: ObservableObject { 11 | 12 | @Published var taskViewModels: [TaskViewModel] = [] 13 | 14 | let dueDateFormatter: DateFormatter = { 15 | let formatter = DateFormatter() 16 | formatter.dateStyle = .short 17 | formatter.timeStyle = .none 18 | return formatter 19 | }() 20 | 21 | func addTask(taskViewModel: TaskViewModel) { 22 | taskViewModels.append(taskViewModel) 23 | } 24 | 25 | func removeTask(at offsets: IndexSet) { 26 | taskViewModels.remove(atOffsets: offsets) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/TaskView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TaskView.swift 3 | // TasksAppWithChatGpt 4 | // 5 | // Created by Eric Callanan on 19/03/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TaskView: View { 11 | @Binding var task: Task // change to a binding 12 | 13 | var body: some View { 14 | VStack(alignment: .leading) { 15 | Text(task.title) 16 | if let dueDate = task.dueDate { 17 | Text("Due date: \(dueDate, formatter: ContentView.taskDateFormat)") 18 | .font(.caption) 19 | } 20 | Text("Status: \(task.status.rawValue)") 21 | } 22 | .foregroundColor(task.completed ? .gray : .primary) 23 | .opacity(task.completed ? 0.5 : 1) 24 | } 25 | } 26 | 27 | struct TaskView_Previews: PreviewProvider { 28 | static var previews: some View { 29 | TaskView(task: .constant(Task(id: UUID(), 30 | title: "Preview Task", 31 | dueDate: Date(), 32 | status: .inProgress))) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/TaskViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TaskViewModel.swift 3 | // TasksAppWithChatGpt 4 | // 5 | // Created by Eric Callanan on 17/03/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | class TaskViewModel: ObservableObject { 11 | private let userDefaults: UserDefaults 12 | @Published var tasks: [Task] 13 | @Published var isEditing = false 14 | 15 | init() { 16 | self.userDefaults = UserDefaults.standard 17 | self.tasks = [] 18 | 19 | if let savedTasksData = userDefaults.data(forKey: "tasks"), 20 | let savedTasks = try? JSONDecoder().decode([Task].self, from: savedTasksData) { 21 | self.tasks = savedTasks 22 | } 23 | } 24 | 25 | func saveTasks() { 26 | if let encodedTasks = try? JSONEncoder().encode(tasks) { 27 | userDefaults.set(encodedTasks, forKey: "tasks") 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGpt/TasksAppWithChatGptApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TasksAppWithChatGptApp.swift 3 | // TasksAppWithChatGpt 4 | // 5 | // Created by Eric Callanan on 17/03/2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct TasksAppWithChatGptApp: App { 12 | @Environment(\.scenePhase) private var scenePhase 13 | 14 | let taskViewModel = TaskViewModel() 15 | 16 | var body: some Scene { 17 | WindowGroup { 18 | ContentView() 19 | .environmentObject(taskViewModel) 20 | } 21 | .onChange(of: scenePhase) { newScenePhase in 22 | if newScenePhase == .inactive || newScenePhase == .background { 23 | taskViewModel.saveTasks() 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/TasksAppWithChatGptTests/TasksAppWithChatGptTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TasksAppWithChatGptTests.swift 3 | // TasksAppWithChatGptTests 4 | // 5 | // Created by Eric Callanan on 17/03/2023. 6 | // 7 | 8 | import XCTest 9 | @testable import TasksAppWithChatGpt 10 | 11 | class TaskViewModelTests: XCTestCase { 12 | var viewModel: TaskViewModel! 13 | 14 | override func setUp() { 15 | viewModel = TaskViewModel() 16 | } 17 | 18 | override func tearDown() { 19 | viewModel = nil 20 | } 21 | 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /TasksAppWithChatGpt/images/edit-tasks-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TasksAppWithChatGpt/images/edit-tasks-view.png -------------------------------------------------------------------------------- /TasksAppWithChatGpt/images/editing-tasks-not-working.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TasksAppWithChatGpt/images/editing-tasks-not-working.gif -------------------------------------------------------------------------------- /TasksAppWithChatGpt/images/light-and-dark-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TasksAppWithChatGpt/images/light-and-dark-mode.png -------------------------------------------------------------------------------- /TasksAppWithChatGpt/images/tasklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TasksAppWithChatGpt/images/tasklist.png -------------------------------------------------------------------------------- /TasksAppWithChatGpt/images/tasks-persisted.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TasksAppWithChatGpt/images/tasks-persisted.gif -------------------------------------------------------------------------------- /TicTacToe/README.md: -------------------------------------------------------------------------------- 1 | ## TicTacToe is a SwiftUI app to play Tic Tac Toe 2 | 3 | 4 |
5 | 6 | This is an App I developed to explore TDD in SwiftUI. 7 | 8 | 9 |
10 | 11 | Full article is 12 | Fixing a bug in Tic Tac Toe with TDD 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | ### Sample Tic Tac Toe game 22 | tic tac toe sample game 25 | 26 |
27 | 28 | 29 | 30 |
31 | 32 | 33 | ### Minimax algorithm with weight factor to give increased score for a win in less moves 34 | minimax-path-for-o-player-adjusted-scores.png 37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 |
48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcbaselines/9ADCA25E270EC1B9002DA2FA.xcbaseline/D3905B57-9DA6-4F5A-A259-337FFADB3DBE.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | TicGameModelPerformanceTests 8 | 9 | testFirstMove2() 10 | 11 | com.apple.dt.XCTMetric_Clock.time.monotonic 12 | 13 | baselineAverage 14 | 1.537560 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcbaselines/9ADCA25E270EC1B9002DA2FA.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | D3905B57-9DA6-4F5A-A259-337FFADB3DBE 8 | 9 | localComputer 10 | 11 | busSpeedInMHz 12 | 0 13 | cpuCount 14 | 1 15 | cpuKind 16 | Apple M1 Max 17 | cpuSpeedInMHz 18 | 0 19 | logicalCPUCoresPerPackage 20 | 10 21 | modelCode 22 | MacBookPro18,2 23 | physicalCPUCoresPerPackage 24 | 10 25 | platformIdentifier 26 | com.apple.platform.macosx 27 | 28 | targetArchitecture 29 | arm64 30 | targetDevice 31 | 32 | modelCode 33 | iPhone14,2 34 | platformIdentifier 35 | com.apple.platform.iphonesimulator 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/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 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Assets.xcassets/Test.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "100", 9 | "green" : "40", 10 | "red" : "100" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "extended-srgb", 24 | "components" : { 25 | "alpha" : "0.670", 26 | "blue" : "140", 27 | "green" : "200", 28 | "red" : "100" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Assets.xcassets/redgreen.imageset/00_red_green_refactor_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TicTacToe/TicTacToe/Assets.xcassets/redgreen.imageset/00_red_green_refactor_diagram.png -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Assets.xcassets/redgreen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "00_red_green_refactor_diagram.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Assets.xcassets/tictactoegrid.imageset/01_tic_tac_toe_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TicTacToe/TicTacToe/Assets.xcassets/tictactoegrid.imageset/01_tic_tac_toe_grid.png -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Assets.xcassets/tictactoegrid.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "01_tic_tac_toe_grid.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Models/TicBoardModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TicBoardModel.swift 3 | // TicTacToe 4 | // 5 | // Created by Eric Callanan on 30/10/2021. 6 | // 7 | 8 | import Foundation 9 | 10 | enum Cell: String { 11 | case x = "X" 12 | case o = "O" 13 | case b = "" // blank 14 | } 15 | 16 | struct TicBoardModel { 17 | var grid: [Cell] 18 | 19 | init(cells: [Cell]) { 20 | grid = cells 21 | } 22 | 23 | init(cells: [Cell], n: Int, c: Cell) { 24 | grid = cells 25 | grid[n] = c 26 | } 27 | 28 | var availableCells: [Int] { 29 | get { grid.indices.filter { grid[$0] == .b } } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/TicTacToeApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TicTacToeApp.swift 3 | // TicTacToe 4 | // 5 | // Created by Eric Callanan on 06/10/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct TicTacToeApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | TicTacToeView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TicTacToe/TicTacToe/Views/ActivePlayerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivePlayerView.swift 3 | // TicTacToe 4 | // 5 | // Created by Eric Callanan on 14/10/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ActivePlayerView: View { 11 | var isActive: Bool 12 | var player: String 13 | 14 | var body: some View { 15 | RoundedRectangle(cornerRadius: 10) 16 | .fill(isActive ? Colors.activeGradient : Colors.inactiveGradient) 17 | .frame(width:120, height:30) 18 | .overlay( 19 | Text(player)) 20 | .font(.system(size: 20, weight: .bold, design: .rounded)) 21 | .foregroundColor(.white) 22 | .scaleEffect(isActive ? 1.0 : 0.85) 23 | .animation(.easeInOut(duration: 0.5)) 24 | } 25 | } 26 | 27 | struct ActivePlayerView_Previews: PreviewProvider { 28 | static var previews: some View { 29 | VStack { 30 | ActivePlayerView(isActive: true, player: "player One") 31 | ActivePlayerView(isActive: false, player: "player two") 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /TicTacToe/images/minimax-path-for-o-player-adjusted-scores.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TicTacToe/images/minimax-path-for-o-player-adjusted-scores.png -------------------------------------------------------------------------------- /TicTacToe/images/tic-tac-toe.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/TicTacToe/images/tic-tac-toe.gif -------------------------------------------------------------------------------- /images/BarChart-top-section.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/images/BarChart-top-section.png -------------------------------------------------------------------------------- /images/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/images/heart.png -------------------------------------------------------------------------------- /images/horizontal-scroll-on-swift-charts.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/images/horizontal-scroll-on-swift-charts.gif -------------------------------------------------------------------------------- /images/matching-colors-with-hsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/images/matching-colors-with-hsb.png -------------------------------------------------------------------------------- /images/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/images/star.png -------------------------------------------------------------------------------- /images/steps-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/images/steps-chart.png -------------------------------------------------------------------------------- /images/three-column-multi-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calleric/swift/a03fb93854a48c0cc083aa906ecb8ec87981b0b2/images/three-column-multi-select.png --------------------------------------------------------------------------------