├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ └── swiftui-issue.md ├── .gitignore ├── Example ├── Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Example │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon-1024.png │ │ ├── icon-20-ipad.png │ │ ├── icon-20@2x-ipad.png │ │ ├── icon-20@2x.png │ │ ├── icon-20@3x.png │ │ ├── icon-29-ipad.png │ │ ├── icon-29.png │ │ ├── icon-29@2x-ipad.png │ │ ├── icon-29@2x.png │ │ ├── icon-29@3x.png │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-40@3x.png │ │ ├── icon-50.png │ │ ├── icon-50@2x.png │ │ ├── icon-57.png │ │ ├── icon-57@2x.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-72.png │ │ ├── icon-72@2x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ └── icon-83.5@2x.png │ ├── Contents.json │ ├── g.imageset │ │ ├── Contents.json │ │ └── g.jpg │ ├── icon.imageset │ │ ├── Contents.json │ │ └── icon.png │ └── tab │ │ ├── Contents.json │ │ ├── add.imageset │ │ ├── Contents.json │ │ ├── add.png │ │ ├── add@2x.png │ │ └── add@3x.png │ │ ├── hot.imageset │ │ ├── Contents.json │ │ ├── hot.png │ │ ├── hot@2x.png │ │ └── hot@3x.png │ │ ├── recommend.imageset │ │ ├── Contents.json │ │ ├── recommend.png │ │ ├── recommend@2x.png │ │ └── recommend@3x.png │ │ ├── search.imageset │ │ ├── Contents.json │ │ ├── search.png │ │ ├── search@2x.png │ │ └── search@3x.png │ │ ├── setting.imageset │ │ ├── Contents.json │ │ ├── setting.png │ │ ├── setting@2x.png │ │ └── setting@3x.png │ │ └── tag.imageset │ │ ├── Contents.json │ │ ├── tag.png │ │ ├── tag@2x.png │ │ └── tag@3x.png │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── ContentView.swift │ ├── Example.entitlements │ ├── Extension │ ├── Color+Ext.swift │ ├── View+Ext.swift │ └── Window+Ext.swift │ ├── Info.plist │ ├── Page │ ├── Alert │ │ ├── ActionSheetPage.swift │ │ ├── AlertPage.swift │ │ ├── ModalPage.swift │ │ └── PopoverPage.swift │ ├── Button │ │ ├── ButtonPage.swift │ │ ├── EditButtonPage.swift │ │ └── NavigationButtonPage.swift │ ├── Container │ │ ├── FormPage.swift │ │ ├── GroupPage.swift │ │ └── SectionPage.swift │ ├── Image │ │ ├── ImagePage.swift │ │ └── WebImagePage.swift │ ├── List │ │ ├── ForEachPage.swift │ │ ├── ListPage.swift │ │ └── ScrollViewPage.swift │ ├── Lottery │ │ ├── LotteryControl.swift │ │ └── LotteryView.swift │ ├── Navigation │ │ ├── NavigationViewPage.swift │ │ └── TableViewPage.swift │ ├── Picker │ │ ├── DatePickerPage.swift │ │ ├── PickerPage.swift │ │ ├── SegmentedControlPage.swift │ │ ├── SliderPage.swift │ │ ├── StepperPage.swift │ │ └── TogglePage.swift │ ├── SpecialPage │ │ ├── ControllerPage.swift │ │ ├── SpacerPage.swift │ │ ├── UIKitController.swift │ │ └── WebViewPage.swift │ ├── Stack │ │ ├── HStackPage.swift │ │ ├── VStackPage.swift │ │ └── ZStackPage.swift │ └── Text │ │ ├── TextFieldPage.swift │ │ └── TextPage.swift │ ├── PageRow.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── SceneDelegate.swift ├── LICENSE ├── README.md ├── README_CN.md ├── _config.yml └── images ├── ad ├── cn.png └── en.png ├── example ├── ActionSheet.png ├── Alert.png ├── AlertPage.jpg ├── Button.png ├── DatePicker.png ├── EditButton.png ├── Field.png ├── ForEach.png ├── Form.png ├── Group.png ├── HStack.png ├── Image.png ├── List.png ├── Modal.png ├── NavigationButton.png ├── NavigationView.png ├── Picker.png ├── Popover.png ├── PresentationButton.png ├── ScrollView.png ├── Section.png ├── SegmentedControl.png ├── Slider.png ├── Stepper.png ├── TabView.png ├── Text.png ├── Toggle.png ├── UIViewController.png ├── UIViewController2.png ├── VStack.png ├── WebImage.png ├── WebView.png └── ZStack.png ├── icon ├── banner.png ├── icon.png ├── icon2.png ├── swiftUI.sketch └── top.png ├── screenshot ├── x1.jpg └── x2.jpg └── windows11 └── launchpad.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [Jinxiansen] # 2 | open_collective: SwiftUI 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/swiftui-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: SwiftUI issue 3 | about: Describe and give feedback on problems you have encountered. 4 | title: SwiftUI issue 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Version 11 | macOS version: 12 | 13 | Xcode version: 14 | 15 | ## Description 16 | 17 | Describe your problem: 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # macOS 2 | .DS_Store 3 | 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData/ 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata/ 22 | 23 | ## Other 24 | *.moved-aside 25 | *.xccheckout 26 | *.xcscmblueprint 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | *.dSYM.zip 32 | *.dSYM 33 | 34 | ## Playgrounds 35 | timeline.xctimeline 36 | playground.xcworkspace 37 | 38 | # Swift Package Manager 39 | # 40 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 41 | # Packages/ 42 | # Package.pins 43 | # Package.resolved 44 | .build/ 45 | 46 | # CocoaPods 47 | # 48 | # We recommend against adding the Pods directory to your .gitignore. However 49 | # you should judge for yourself, the pros and cons are mentioned at: 50 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 51 | # 52 | # Pods/ 53 | 54 | # Carthage 55 | # 56 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 57 | # Carthage/Checkouts 58 | 59 | Carthage/Build 60 | 61 | # fastlane 62 | # 63 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 64 | # screenshots whenever they are needed. 65 | # For more information about the recommended setup visit: 66 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 67 | 68 | fastlane/report.xml 69 | fastlane/Preview.html 70 | fastlane/screenshots/**/*.png 71 | fastlane/test_output 72 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 36F7ED9F2465231100CF20CB /* LotteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F7ED9E2465231100CF20CB /* LotteryView.swift */; }; 11 | 36F7EDA12465265200CF20CB /* LotteryControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F7EDA02465265200CF20CB /* LotteryControl.swift */; }; 12 | 4132A45E22AD561500A8DBBE /* GroupPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4132A45D22AD561500A8DBBE /* GroupPage.swift */; }; 13 | 4132A46022AD624700A8DBBE /* SectionPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4132A45F22AD624700A8DBBE /* SectionPage.swift */; }; 14 | 4132A46322AD709300A8DBBE /* Color+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4132A46222AD709300A8DBBE /* Color+Ext.swift */; }; 15 | 4132A46622AD70D400A8DBBE /* View+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4132A46522AD70D400A8DBBE /* View+Ext.swift */; }; 16 | 4132A46822AE8D5200A8DBBE /* NavigationViewPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4132A46722AE8D5200A8DBBE /* NavigationViewPage.swift */; }; 17 | 4132A46B22B00E6100A8DBBE /* PickerPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4132A46A22B00E6100A8DBBE /* PickerPage.swift */; }; 18 | 415F044922AB8801003E59FC /* SegmentedControlPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 415F044822AB8801003E59FC /* SegmentedControlPage.swift */; }; 19 | 415F044B22AB9A96003E59FC /* AlertPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 415F044A22AB9A95003E59FC /* AlertPage.swift */; }; 20 | 415F044F22ABA1E3003E59FC /* TogglePage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 415F044E22ABA1E3003E59FC /* TogglePage.swift */; }; 21 | 4160444C22B291000052CAFC /* UIKitController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4160444B22B291000052CAFC /* UIKitController.swift */; }; 22 | 4160445122B2987A0052CAFC /* ControllerPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4160445022B2987A0052CAFC /* ControllerPage.swift */; }; 23 | 4161B32722AB68F600CD5A1B /* HStackPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4161B32622AB68F600CD5A1B /* HStackPage.swift */; }; 24 | 4161B32922AB695A00CD5A1B /* VStackPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4161B32822AB695A00CD5A1B /* VStackPage.swift */; }; 25 | 4161B32B22AB696300CD5A1B /* ZStackPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4161B32A22AB696300CD5A1B /* ZStackPage.swift */; }; 26 | 4161B32D22AB6CBE00CD5A1B /* SliderPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4161B32C22AB6CBE00CD5A1B /* SliderPage.swift */; }; 27 | 4161B33022AB6D2900CD5A1B /* ScrollViewPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4161B32F22AB6D2900CD5A1B /* ScrollViewPage.swift */; }; 28 | 4161B33222AB6D3400CD5A1B /* ForEachPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4161B33122AB6D3400CD5A1B /* ForEachPage.swift */; }; 29 | 4161B33422AB83B700CD5A1B /* StepperPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4161B33322AB83B700CD5A1B /* StepperPage.swift */; }; 30 | 4164489D22AA6D6500A93AF2 /* ImagePage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4164489C22AA6D6500A93AF2 /* ImagePage.swift */; }; 31 | 4196ABC822A97AB1008B8FD2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4196ABC722A97AB1008B8FD2 /* AppDelegate.swift */; }; 32 | 4196ABCA22A97AB1008B8FD2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4196ABC922A97AB1008B8FD2 /* SceneDelegate.swift */; }; 33 | 4196ABCC22A97AB1008B8FD2 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4196ABCB22A97AB1008B8FD2 /* ContentView.swift */; }; 34 | 4196ABCE22A97AB2008B8FD2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4196ABCD22A97AB2008B8FD2 /* Assets.xcassets */; }; 35 | 4196ABD122A97AB2008B8FD2 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4196ABD022A97AB2008B8FD2 /* Preview Assets.xcassets */; }; 36 | 4196ABD422A97AB2008B8FD2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4196ABD222A97AB2008B8FD2 /* LaunchScreen.storyboard */; }; 37 | 4196ABDC22A97D61008B8FD2 /* PageRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4196ABDB22A97D61008B8FD2 /* PageRow.swift */; }; 38 | 4196ABE222AA1B80008B8FD2 /* TextPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4196ABE122AA1B80008B8FD2 /* TextPage.swift */; }; 39 | 4196ABE722AA268A008B8FD2 /* TextFieldPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4196ABE622AA268A008B8FD2 /* TextFieldPage.swift */; }; 40 | 41977FF522ACA74600FD47FE /* WebImagePage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41977FF422ACA74600FD47FE /* WebImagePage.swift */; }; 41 | 41C7E65E22B4A9680074D4F6 /* ModalPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41C7E65D22B4A9680074D4F6 /* ModalPage.swift */; }; 42 | 41E4DCCE22B4ADB000F78522 /* PopoverPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E4DCCD22B4ADB000F78522 /* PopoverPage.swift */; }; 43 | 41E4DCD022B4B4FF00F78522 /* ActionSheetPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41E4DCCF22B4B4FF00F78522 /* ActionSheetPage.swift */; }; 44 | 41F36F0A22AA84D600B9172D /* ButtonPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F36F0922AA84D600B9172D /* ButtonPage.swift */; }; 45 | 41F36F0C22AA87AF00B9172D /* TableViewPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F36F0B22AA87AF00B9172D /* TableViewPage.swift */; }; 46 | 41F36F0E22AA8AEC00B9172D /* WebViewPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F36F0D22AA8AEC00B9172D /* WebViewPage.swift */; }; 47 | 41F36F1022AA915300B9172D /* ListPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F36F0F22AA915300B9172D /* ListPage.swift */; }; 48 | 41FE99E722AAD08A008135A0 /* NavigationButtonPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41FE99E622AAD08A008135A0 /* NavigationButtonPage.swift */; }; 49 | 41FE99E922AAD7B0008135A0 /* EditButtonPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41FE99E822AAD7B0008135A0 /* EditButtonPage.swift */; }; 50 | 41FE99F022AADF9F008135A0 /* DatePickerPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41FE99EF22AADF9F008135A0 /* DatePickerPage.swift */; }; 51 | BD99734E23B49BB800A3E3F0 /* FormPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD99734D23B49BB800A3E3F0 /* FormPage.swift */; }; 52 | D74985BC231634DA00C4D46D /* Window+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74985BB231634DA00C4D46D /* Window+Ext.swift */; }; 53 | FC8DE9B929309F3D00A5C8FF /* SpacerPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC8DE9B829309F3D00A5C8FF /* SpacerPage.swift */; }; 54 | /* End PBXBuildFile section */ 55 | 56 | /* Begin PBXFileReference section */ 57 | 36F7ED9E2465231100CF20CB /* LotteryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LotteryView.swift; sourceTree = "<group>"; }; 58 | 36F7EDA02465265200CF20CB /* LotteryControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LotteryControl.swift; sourceTree = "<group>"; }; 59 | 4117B81624946600000F4BF8 /* Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Example.entitlements; sourceTree = "<group>"; }; 60 | 4132A45D22AD561500A8DBBE /* GroupPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupPage.swift; sourceTree = "<group>"; }; 61 | 4132A45F22AD624700A8DBBE /* SectionPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionPage.swift; sourceTree = "<group>"; }; 62 | 4132A46222AD709300A8DBBE /* Color+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Ext.swift"; sourceTree = "<group>"; }; 63 | 4132A46522AD70D400A8DBBE /* View+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Ext.swift"; sourceTree = "<group>"; }; 64 | 4132A46722AE8D5200A8DBBE /* NavigationViewPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewPage.swift; sourceTree = "<group>"; }; 65 | 4132A46A22B00E6100A8DBBE /* PickerPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickerPage.swift; sourceTree = "<group>"; }; 66 | 415F044822AB8801003E59FC /* SegmentedControlPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedControlPage.swift; sourceTree = "<group>"; }; 67 | 415F044A22AB9A95003E59FC /* AlertPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertPage.swift; sourceTree = "<group>"; }; 68 | 415F044E22ABA1E3003E59FC /* TogglePage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TogglePage.swift; sourceTree = "<group>"; }; 69 | 4160444B22B291000052CAFC /* UIKitController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitController.swift; sourceTree = "<group>"; }; 70 | 4160445022B2987A0052CAFC /* ControllerPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControllerPage.swift; sourceTree = "<group>"; }; 71 | 4161B32622AB68F600CD5A1B /* HStackPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HStackPage.swift; sourceTree = "<group>"; }; 72 | 4161B32822AB695A00CD5A1B /* VStackPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VStackPage.swift; sourceTree = "<group>"; }; 73 | 4161B32A22AB696300CD5A1B /* ZStackPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZStackPage.swift; sourceTree = "<group>"; }; 74 | 4161B32C22AB6CBE00CD5A1B /* SliderPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderPage.swift; sourceTree = "<group>"; }; 75 | 4161B32F22AB6D2900CD5A1B /* ScrollViewPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewPage.swift; sourceTree = "<group>"; }; 76 | 4161B33122AB6D3400CD5A1B /* ForEachPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForEachPage.swift; sourceTree = "<group>"; }; 77 | 4161B33322AB83B700CD5A1B /* StepperPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepperPage.swift; sourceTree = "<group>"; }; 78 | 4164489C22AA6D6500A93AF2 /* ImagePage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePage.swift; sourceTree = "<group>"; }; 79 | 4196ABC422A97AB1008B8FD2 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 80 | 4196ABC722A97AB1008B8FD2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 81 | 4196ABC922A97AB1008B8FD2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; }; 82 | 4196ABCB22A97AB1008B8FD2 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; 83 | 4196ABCD22A97AB2008B8FD2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 84 | 4196ABD022A97AB2008B8FD2 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; }; 85 | 4196ABD322A97AB2008B8FD2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 86 | 4196ABD522A97AB2008B8FD2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 87 | 4196ABDB22A97D61008B8FD2 /* PageRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageRow.swift; sourceTree = "<group>"; }; 88 | 4196ABE122AA1B80008B8FD2 /* TextPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextPage.swift; sourceTree = "<group>"; }; 89 | 4196ABE622AA268A008B8FD2 /* TextFieldPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldPage.swift; sourceTree = "<group>"; }; 90 | 41977FF422ACA74600FD47FE /* WebImagePage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebImagePage.swift; sourceTree = "<group>"; }; 91 | 41C7E65D22B4A9680074D4F6 /* ModalPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalPage.swift; sourceTree = "<group>"; }; 92 | 41E4DCCD22B4ADB000F78522 /* PopoverPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopoverPage.swift; sourceTree = "<group>"; }; 93 | 41E4DCCF22B4B4FF00F78522 /* ActionSheetPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionSheetPage.swift; sourceTree = "<group>"; }; 94 | 41F36F0922AA84D600B9172D /* ButtonPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonPage.swift; sourceTree = "<group>"; }; 95 | 41F36F0B22AA87AF00B9172D /* TableViewPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewPage.swift; sourceTree = "<group>"; }; 96 | 41F36F0D22AA8AEC00B9172D /* WebViewPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewPage.swift; sourceTree = "<group>"; }; 97 | 41F36F0F22AA915300B9172D /* ListPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListPage.swift; sourceTree = "<group>"; }; 98 | 41FE99E622AAD08A008135A0 /* NavigationButtonPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationButtonPage.swift; sourceTree = "<group>"; }; 99 | 41FE99E822AAD7B0008135A0 /* EditButtonPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditButtonPage.swift; sourceTree = "<group>"; }; 100 | 41FE99EF22AADF9F008135A0 /* DatePickerPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerPage.swift; sourceTree = "<group>"; }; 101 | BD99734D23B49BB800A3E3F0 /* FormPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormPage.swift; sourceTree = "<group>"; }; 102 | D74985BB231634DA00C4D46D /* Window+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Window+Ext.swift"; sourceTree = "<group>"; }; 103 | FC8DE9B829309F3D00A5C8FF /* SpacerPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpacerPage.swift; sourceTree = "<group>"; }; 104 | /* End PBXFileReference section */ 105 | 106 | /* Begin PBXFrameworksBuildPhase section */ 107 | 4196ABC122A97AB1008B8FD2 /* Frameworks */ = { 108 | isa = PBXFrameworksBuildPhase; 109 | buildActionMask = 2147483647; 110 | files = ( 111 | ); 112 | runOnlyForDeploymentPostprocessing = 0; 113 | }; 114 | /* End PBXFrameworksBuildPhase section */ 115 | 116 | /* Begin PBXGroup section */ 117 | 36F7ED9D246522E000CF20CB /* Lottery */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 36F7ED9E2465231100CF20CB /* LotteryView.swift */, 121 | 36F7EDA02465265200CF20CB /* LotteryControl.swift */, 122 | ); 123 | path = Lottery; 124 | sourceTree = "<group>"; 125 | }; 126 | 4132A46122AD700F00A8DBBE /* Container */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 4132A45D22AD561500A8DBBE /* GroupPage.swift */, 130 | 4132A45F22AD624700A8DBBE /* SectionPage.swift */, 131 | BD99734D23B49BB800A3E3F0 /* FormPage.swift */, 132 | ); 133 | path = Container; 134 | sourceTree = "<group>"; 135 | }; 136 | 4132A46422AD70B400A8DBBE /* Extension */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 4132A46222AD709300A8DBBE /* Color+Ext.swift */, 140 | 4132A46522AD70D400A8DBBE /* View+Ext.swift */, 141 | D74985BB231634DA00C4D46D /* Window+Ext.swift */, 142 | ); 143 | path = Extension; 144 | sourceTree = "<group>"; 145 | }; 146 | 4132A46922AEB15A00A8DBBE /* Navigation */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 4132A46722AE8D5200A8DBBE /* NavigationViewPage.swift */, 150 | 41F36F0B22AA87AF00B9172D /* TableViewPage.swift */, 151 | ); 152 | path = Navigation; 153 | sourceTree = "<group>"; 154 | }; 155 | 415F044C22ABA043003E59FC /* Picker */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 4132A46A22B00E6100A8DBBE /* PickerPage.swift */, 159 | 41FE99EF22AADF9F008135A0 /* DatePickerPage.swift */, 160 | 415F044E22ABA1E3003E59FC /* TogglePage.swift */, 161 | 4161B32C22AB6CBE00CD5A1B /* SliderPage.swift */, 162 | 4161B33322AB83B700CD5A1B /* StepperPage.swift */, 163 | 415F044822AB8801003E59FC /* SegmentedControlPage.swift */, 164 | ); 165 | path = Picker; 166 | sourceTree = "<group>"; 167 | }; 168 | 415F044D22ABA051003E59FC /* List */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | 41F36F0F22AA915300B9172D /* ListPage.swift */, 172 | 4161B32F22AB6D2900CD5A1B /* ScrollViewPage.swift */, 173 | 4161B33122AB6D3400CD5A1B /* ForEachPage.swift */, 174 | ); 175 | path = List; 176 | sourceTree = "<group>"; 177 | }; 178 | 4160444F22B2985D0052CAFC /* SpecialPage */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | 41F36F0D22AA8AEC00B9172D /* WebViewPage.swift */, 182 | 4160445022B2987A0052CAFC /* ControllerPage.swift */, 183 | 4160444B22B291000052CAFC /* UIKitController.swift */, 184 | FC8DE9B829309F3D00A5C8FF /* SpacerPage.swift */, 185 | ); 186 | path = SpecialPage; 187 | sourceTree = "<group>"; 188 | }; 189 | 4161B32E22AB6D0F00CD5A1B /* Stack */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 4161B32622AB68F600CD5A1B /* HStackPage.swift */, 193 | 4161B32822AB695A00CD5A1B /* VStackPage.swift */, 194 | 4161B32A22AB696300CD5A1B /* ZStackPage.swift */, 195 | ); 196 | path = Stack; 197 | sourceTree = "<group>"; 198 | }; 199 | 4196ABBB22A97AB1008B8FD2 = { 200 | isa = PBXGroup; 201 | children = ( 202 | 4196ABC622A97AB1008B8FD2 /* Example */, 203 | 4196ABC522A97AB1008B8FD2 /* Products */, 204 | ); 205 | sourceTree = "<group>"; 206 | }; 207 | 4196ABC522A97AB1008B8FD2 /* Products */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | 4196ABC422A97AB1008B8FD2 /* Example.app */, 211 | ); 212 | name = Products; 213 | sourceTree = "<group>"; 214 | }; 215 | 4196ABC622A97AB1008B8FD2 /* Example */ = { 216 | isa = PBXGroup; 217 | children = ( 218 | 4117B81624946600000F4BF8 /* Example.entitlements */, 219 | 4196ABC722A97AB1008B8FD2 /* AppDelegate.swift */, 220 | 4196ABC922A97AB1008B8FD2 /* SceneDelegate.swift */, 221 | 4196ABCB22A97AB1008B8FD2 /* ContentView.swift */, 222 | 4196ABDB22A97D61008B8FD2 /* PageRow.swift */, 223 | 4196ABE522AA24B4008B8FD2 /* Page */, 224 | 4132A46422AD70B400A8DBBE /* Extension */, 225 | 4196ABCD22A97AB2008B8FD2 /* Assets.xcassets */, 226 | 4196ABD222A97AB2008B8FD2 /* LaunchScreen.storyboard */, 227 | 4196ABD522A97AB2008B8FD2 /* Info.plist */, 228 | 4196ABCF22A97AB2008B8FD2 /* Preview Content */, 229 | ); 230 | path = Example; 231 | sourceTree = "<group>"; 232 | }; 233 | 4196ABCF22A97AB2008B8FD2 /* Preview Content */ = { 234 | isa = PBXGroup; 235 | children = ( 236 | 4196ABD022A97AB2008B8FD2 /* Preview Assets.xcassets */, 237 | ); 238 | path = "Preview Content"; 239 | sourceTree = "<group>"; 240 | }; 241 | 4196ABE522AA24B4008B8FD2 /* Page */ = { 242 | isa = PBXGroup; 243 | children = ( 244 | 36F7ED9D246522E000CF20CB /* Lottery */, 245 | 4160444F22B2985D0052CAFC /* SpecialPage */, 246 | 41FE99ED22AADF7C008135A0 /* Text */, 247 | 41FE99EE22AADF8E008135A0 /* Image */, 248 | 41FE99EC22AADF6E008135A0 /* Button */, 249 | 415F044D22ABA051003E59FC /* List */, 250 | 415F044C22ABA043003E59FC /* Picker */, 251 | 4132A46922AEB15A00A8DBBE /* Navigation */, 252 | 4132A46122AD700F00A8DBBE /* Container */, 253 | 4161B32E22AB6D0F00CD5A1B /* Stack */, 254 | 41C7E65F22B4A96C0074D4F6 /* Alert */, 255 | ); 256 | path = Page; 257 | sourceTree = "<group>"; 258 | }; 259 | 41C7E65F22B4A96C0074D4F6 /* Alert */ = { 260 | isa = PBXGroup; 261 | children = ( 262 | 415F044A22AB9A95003E59FC /* AlertPage.swift */, 263 | 41E4DCCF22B4B4FF00F78522 /* ActionSheetPage.swift */, 264 | 41C7E65D22B4A9680074D4F6 /* ModalPage.swift */, 265 | 41E4DCCD22B4ADB000F78522 /* PopoverPage.swift */, 266 | ); 267 | path = Alert; 268 | sourceTree = "<group>"; 269 | }; 270 | 41FE99EC22AADF6E008135A0 /* Button */ = { 271 | isa = PBXGroup; 272 | children = ( 273 | 41F36F0922AA84D600B9172D /* ButtonPage.swift */, 274 | 41FE99E622AAD08A008135A0 /* NavigationButtonPage.swift */, 275 | 41FE99E822AAD7B0008135A0 /* EditButtonPage.swift */, 276 | ); 277 | path = Button; 278 | sourceTree = "<group>"; 279 | }; 280 | 41FE99ED22AADF7C008135A0 /* Text */ = { 281 | isa = PBXGroup; 282 | children = ( 283 | 4196ABE122AA1B80008B8FD2 /* TextPage.swift */, 284 | 4196ABE622AA268A008B8FD2 /* TextFieldPage.swift */, 285 | ); 286 | path = Text; 287 | sourceTree = "<group>"; 288 | }; 289 | 41FE99EE22AADF8E008135A0 /* Image */ = { 290 | isa = PBXGroup; 291 | children = ( 292 | 4164489C22AA6D6500A93AF2 /* ImagePage.swift */, 293 | 41977FF422ACA74600FD47FE /* WebImagePage.swift */, 294 | ); 295 | path = Image; 296 | sourceTree = "<group>"; 297 | }; 298 | /* End PBXGroup section */ 299 | 300 | /* Begin PBXNativeTarget section */ 301 | 4196ABC322A97AB1008B8FD2 /* Example */ = { 302 | isa = PBXNativeTarget; 303 | buildConfigurationList = 4196ABD822A97AB2008B8FD2 /* Build configuration list for PBXNativeTarget "Example" */; 304 | buildPhases = ( 305 | 4196ABC022A97AB1008B8FD2 /* Sources */, 306 | 4196ABC122A97AB1008B8FD2 /* Frameworks */, 307 | 4196ABC222A97AB1008B8FD2 /* Resources */, 308 | ); 309 | buildRules = ( 310 | ); 311 | dependencies = ( 312 | ); 313 | name = Example; 314 | productName = Example; 315 | productReference = 4196ABC422A97AB1008B8FD2 /* Example.app */; 316 | productType = "com.apple.product-type.application"; 317 | }; 318 | /* End PBXNativeTarget section */ 319 | 320 | /* Begin PBXProject section */ 321 | 4196ABBC22A97AB1008B8FD2 /* Project object */ = { 322 | isa = PBXProject; 323 | attributes = { 324 | LastSwiftUpdateCheck = 1100; 325 | LastUpgradeCheck = 1100; 326 | ORGANIZATIONNAME = "晋先森"; 327 | TargetAttributes = { 328 | 4196ABC322A97AB1008B8FD2 = { 329 | CreatedOnToolsVersion = 11.0; 330 | }; 331 | }; 332 | }; 333 | buildConfigurationList = 4196ABBF22A97AB1008B8FD2 /* Build configuration list for PBXProject "Example" */; 334 | compatibilityVersion = "Xcode 9.3"; 335 | developmentRegion = en; 336 | hasScannedForEncodings = 0; 337 | knownRegions = ( 338 | en, 339 | Base, 340 | ); 341 | mainGroup = 4196ABBB22A97AB1008B8FD2; 342 | productRefGroup = 4196ABC522A97AB1008B8FD2 /* Products */; 343 | projectDirPath = ""; 344 | projectRoot = ""; 345 | targets = ( 346 | 4196ABC322A97AB1008B8FD2 /* Example */, 347 | ); 348 | }; 349 | /* End PBXProject section */ 350 | 351 | /* Begin PBXResourcesBuildPhase section */ 352 | 4196ABC222A97AB1008B8FD2 /* Resources */ = { 353 | isa = PBXResourcesBuildPhase; 354 | buildActionMask = 2147483647; 355 | files = ( 356 | 4196ABD422A97AB2008B8FD2 /* LaunchScreen.storyboard in Resources */, 357 | 4196ABD122A97AB2008B8FD2 /* Preview Assets.xcassets in Resources */, 358 | 4196ABCE22A97AB2008B8FD2 /* Assets.xcassets in Resources */, 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | }; 362 | /* End PBXResourcesBuildPhase section */ 363 | 364 | /* Begin PBXSourcesBuildPhase section */ 365 | 4196ABC022A97AB1008B8FD2 /* Sources */ = { 366 | isa = PBXSourcesBuildPhase; 367 | buildActionMask = 2147483647; 368 | files = ( 369 | 41E4DCD022B4B4FF00F78522 /* ActionSheetPage.swift in Sources */, 370 | 4196ABC822A97AB1008B8FD2 /* AppDelegate.swift in Sources */, 371 | 4161B33222AB6D3400CD5A1B /* ForEachPage.swift in Sources */, 372 | 36F7EDA12465265200CF20CB /* LotteryControl.swift in Sources */, 373 | 41977FF522ACA74600FD47FE /* WebImagePage.swift in Sources */, 374 | 36F7ED9F2465231100CF20CB /* LotteryView.swift in Sources */, 375 | 4196ABE722AA268A008B8FD2 /* TextFieldPage.swift in Sources */, 376 | 4161B32722AB68F600CD5A1B /* HStackPage.swift in Sources */, 377 | FC8DE9B929309F3D00A5C8FF /* SpacerPage.swift in Sources */, 378 | D74985BC231634DA00C4D46D /* Window+Ext.swift in Sources */, 379 | 4164489D22AA6D6500A93AF2 /* ImagePage.swift in Sources */, 380 | 4161B32922AB695A00CD5A1B /* VStackPage.swift in Sources */, 381 | 415F044B22AB9A96003E59FC /* AlertPage.swift in Sources */, 382 | 41F36F1022AA915300B9172D /* ListPage.swift in Sources */, 383 | 41F36F0A22AA84D600B9172D /* ButtonPage.swift in Sources */, 384 | 41FE99E722AAD08A008135A0 /* NavigationButtonPage.swift in Sources */, 385 | 4160444C22B291000052CAFC /* UIKitController.swift in Sources */, 386 | 4196ABE222AA1B80008B8FD2 /* TextPage.swift in Sources */, 387 | 4160445122B2987A0052CAFC /* ControllerPage.swift in Sources */, 388 | 4196ABCA22A97AB1008B8FD2 /* SceneDelegate.swift in Sources */, 389 | 4161B32B22AB696300CD5A1B /* ZStackPage.swift in Sources */, 390 | 4161B33022AB6D2900CD5A1B /* ScrollViewPage.swift in Sources */, 391 | 41FE99F022AADF9F008135A0 /* DatePickerPage.swift in Sources */, 392 | 4161B33422AB83B700CD5A1B /* StepperPage.swift in Sources */, 393 | 41F36F0C22AA87AF00B9172D /* TableViewPage.swift in Sources */, 394 | 4132A46B22B00E6100A8DBBE /* PickerPage.swift in Sources */, 395 | 4196ABCC22A97AB1008B8FD2 /* ContentView.swift in Sources */, 396 | 4132A46622AD70D400A8DBBE /* View+Ext.swift in Sources */, 397 | 415F044F22ABA1E3003E59FC /* TogglePage.swift in Sources */, 398 | BD99734E23B49BB800A3E3F0 /* FormPage.swift in Sources */, 399 | 41F36F0E22AA8AEC00B9172D /* WebViewPage.swift in Sources */, 400 | 4132A46022AD624700A8DBBE /* SectionPage.swift in Sources */, 401 | 41C7E65E22B4A9680074D4F6 /* ModalPage.swift in Sources */, 402 | 4196ABDC22A97D61008B8FD2 /* PageRow.swift in Sources */, 403 | 4132A46322AD709300A8DBBE /* Color+Ext.swift in Sources */, 404 | 415F044922AB8801003E59FC /* SegmentedControlPage.swift in Sources */, 405 | 41FE99E922AAD7B0008135A0 /* EditButtonPage.swift in Sources */, 406 | 4132A45E22AD561500A8DBBE /* GroupPage.swift in Sources */, 407 | 4132A46822AE8D5200A8DBBE /* NavigationViewPage.swift in Sources */, 408 | 41E4DCCE22B4ADB000F78522 /* PopoverPage.swift in Sources */, 409 | 4161B32D22AB6CBE00CD5A1B /* SliderPage.swift in Sources */, 410 | ); 411 | runOnlyForDeploymentPostprocessing = 0; 412 | }; 413 | /* End PBXSourcesBuildPhase section */ 414 | 415 | /* Begin PBXVariantGroup section */ 416 | 4196ABD222A97AB2008B8FD2 /* LaunchScreen.storyboard */ = { 417 | isa = PBXVariantGroup; 418 | children = ( 419 | 4196ABD322A97AB2008B8FD2 /* Base */, 420 | ); 421 | name = LaunchScreen.storyboard; 422 | sourceTree = "<group>"; 423 | }; 424 | /* End PBXVariantGroup section */ 425 | 426 | /* Begin XCBuildConfiguration section */ 427 | 4196ABD622A97AB2008B8FD2 /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | ALWAYS_SEARCH_USER_PATHS = NO; 431 | CLANG_ANALYZER_NONNULL = YES; 432 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 434 | CLANG_CXX_LIBRARY = "libc++"; 435 | CLANG_ENABLE_MODULES = YES; 436 | CLANG_ENABLE_OBJC_ARC = YES; 437 | CLANG_ENABLE_OBJC_WEAK = YES; 438 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 439 | CLANG_WARN_BOOL_CONVERSION = YES; 440 | CLANG_WARN_COMMA = YES; 441 | CLANG_WARN_CONSTANT_CONVERSION = YES; 442 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 443 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 444 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INFINITE_RECURSION = YES; 448 | CLANG_WARN_INT_CONVERSION = YES; 449 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 450 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 451 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 452 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 453 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 454 | CLANG_WARN_STRICT_PROTOTYPES = YES; 455 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 456 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 457 | CLANG_WARN_UNREACHABLE_CODE = YES; 458 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 459 | COPY_PHASE_STRIP = NO; 460 | DEBUG_INFORMATION_FORMAT = dwarf; 461 | ENABLE_STRICT_OBJC_MSGSEND = YES; 462 | ENABLE_TESTABILITY = YES; 463 | GCC_C_LANGUAGE_STANDARD = gnu11; 464 | GCC_DYNAMIC_NO_PIC = NO; 465 | GCC_NO_COMMON_BLOCKS = YES; 466 | GCC_OPTIMIZATION_LEVEL = 0; 467 | GCC_PREPROCESSOR_DEFINITIONS = ( 468 | "DEBUG=1", 469 | "$(inherited)", 470 | ); 471 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 472 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 473 | GCC_WARN_UNDECLARED_SELECTOR = YES; 474 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 475 | GCC_WARN_UNUSED_FUNCTION = YES; 476 | GCC_WARN_UNUSED_VARIABLE = YES; 477 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 478 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 479 | MTL_FAST_MATH = YES; 480 | ONLY_ACTIVE_ARCH = YES; 481 | SDKROOT = iphoneos; 482 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 483 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 484 | }; 485 | name = Debug; 486 | }; 487 | 4196ABD722A97AB2008B8FD2 /* Release */ = { 488 | isa = XCBuildConfiguration; 489 | buildSettings = { 490 | ALWAYS_SEARCH_USER_PATHS = NO; 491 | CLANG_ANALYZER_NONNULL = YES; 492 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 493 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 494 | CLANG_CXX_LIBRARY = "libc++"; 495 | CLANG_ENABLE_MODULES = YES; 496 | CLANG_ENABLE_OBJC_ARC = YES; 497 | CLANG_ENABLE_OBJC_WEAK = YES; 498 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 499 | CLANG_WARN_BOOL_CONVERSION = YES; 500 | CLANG_WARN_COMMA = YES; 501 | CLANG_WARN_CONSTANT_CONVERSION = YES; 502 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 503 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 504 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 505 | CLANG_WARN_EMPTY_BODY = YES; 506 | CLANG_WARN_ENUM_CONVERSION = YES; 507 | CLANG_WARN_INFINITE_RECURSION = YES; 508 | CLANG_WARN_INT_CONVERSION = YES; 509 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 510 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 511 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 512 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 513 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 514 | CLANG_WARN_STRICT_PROTOTYPES = YES; 515 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 516 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 517 | CLANG_WARN_UNREACHABLE_CODE = YES; 518 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 519 | COPY_PHASE_STRIP = NO; 520 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 521 | ENABLE_NS_ASSERTIONS = NO; 522 | ENABLE_STRICT_OBJC_MSGSEND = YES; 523 | GCC_C_LANGUAGE_STANDARD = gnu11; 524 | GCC_NO_COMMON_BLOCKS = YES; 525 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 526 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 527 | GCC_WARN_UNDECLARED_SELECTOR = YES; 528 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 529 | GCC_WARN_UNUSED_FUNCTION = YES; 530 | GCC_WARN_UNUSED_VARIABLE = YES; 531 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 532 | MTL_ENABLE_DEBUG_INFO = NO; 533 | MTL_FAST_MATH = YES; 534 | SDKROOT = iphoneos; 535 | SWIFT_COMPILATION_MODE = wholemodule; 536 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 537 | VALIDATE_PRODUCT = YES; 538 | }; 539 | name = Release; 540 | }; 541 | 4196ABD922A97AB2008B8FD2 /* Debug */ = { 542 | isa = XCBuildConfiguration; 543 | buildSettings = { 544 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 545 | CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements; 546 | CODE_SIGN_STYLE = Automatic; 547 | DEVELOPMENT_ASSET_PATHS = "Example/Preview\\ Content"; 548 | DEVELOPMENT_TEAM = 3RDZ44DXB9; 549 | ENABLE_PREVIEWS = YES; 550 | INFOPLIST_FILE = Example/Info.plist; 551 | LD_RUNPATH_SEARCH_PATHS = ( 552 | "$(inherited)", 553 | "@executable_path/Frameworks", 554 | ); 555 | PRODUCT_BUNDLE_IDENTIFIER = com.jinxiansen.Example; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | SUPPORTS_MACCATALYST = YES; 558 | SWIFT_VERSION = 5.0; 559 | TARGETED_DEVICE_FAMILY = "1,2"; 560 | }; 561 | name = Debug; 562 | }; 563 | 4196ABDA22A97AB2008B8FD2 /* Release */ = { 564 | isa = XCBuildConfiguration; 565 | buildSettings = { 566 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 567 | CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements; 568 | CODE_SIGN_STYLE = Automatic; 569 | DEVELOPMENT_ASSET_PATHS = "Example/Preview\\ Content"; 570 | DEVELOPMENT_TEAM = 3RDZ44DXB9; 571 | ENABLE_PREVIEWS = YES; 572 | INFOPLIST_FILE = Example/Info.plist; 573 | LD_RUNPATH_SEARCH_PATHS = ( 574 | "$(inherited)", 575 | "@executable_path/Frameworks", 576 | ); 577 | PRODUCT_BUNDLE_IDENTIFIER = com.jinxiansen.Example; 578 | PRODUCT_NAME = "$(TARGET_NAME)"; 579 | SUPPORTS_MACCATALYST = YES; 580 | SWIFT_VERSION = 5.0; 581 | TARGETED_DEVICE_FAMILY = "1,2"; 582 | }; 583 | name = Release; 584 | }; 585 | /* End XCBuildConfiguration section */ 586 | 587 | /* Begin XCConfigurationList section */ 588 | 4196ABBF22A97AB1008B8FD2 /* Build configuration list for PBXProject "Example" */ = { 589 | isa = XCConfigurationList; 590 | buildConfigurations = ( 591 | 4196ABD622A97AB2008B8FD2 /* Debug */, 592 | 4196ABD722A97AB2008B8FD2 /* Release */, 593 | ); 594 | defaultConfigurationIsVisible = 0; 595 | defaultConfigurationName = Release; 596 | }; 597 | 4196ABD822A97AB2008B8FD2 /* Build configuration list for PBXNativeTarget "Example" */ = { 598 | isa = XCConfigurationList; 599 | buildConfigurations = ( 600 | 4196ABD922A97AB2008B8FD2 /* Debug */, 601 | 4196ABDA22A97AB2008B8FD2 /* Release */, 602 | ); 603 | defaultConfigurationIsVisible = 0; 604 | defaultConfigurationName = Release; 605 | }; 606 | /* End XCConfigurationList section */ 607 | }; 608 | rootObject = 4196ABBC22A97AB1008B8FD2 /* Project object */; 609 | } 610 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Workspace 3 | version = "1.0"> 4 | <FileRef 5 | location = "self:Example.xcodeproj"> 6 | </FileRef> 7 | </Workspace> 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>IDEDidComputeMac32BitWarning</key> 6 | <true/> 7 | </dict> 8 | </plist> 9 | -------------------------------------------------------------------------------- /Example/Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillTerminate(_ application: UIApplication) { 22 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 23 | } 24 | 25 | // MARK: UISceneSession Lifecycle 26 | 27 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 28 | // Called when a new scene session is being created. 29 | // Use this method to select a configuration to create the new scene with. 30 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 31 | } 32 | 33 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) { 34 | // Called when the user discards a scene session. 35 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 36 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 37 | } 38 | 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon-29.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "icon-29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "icon-29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "icon-40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "icon-40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "icon-57.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "icon-57@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "icon-60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "icon-60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "icon-20-ipad.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "icon-20@2x-ipad.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "icon-29-ipad.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "icon-29@2x-ipad.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "icon-40.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "icon-40@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "icon-50.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "50x50", 113 | "idiom" : "ipad", 114 | "filename" : "icon-50@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "icon-72.png", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "size" : "72x72", 125 | "idiom" : "ipad", 126 | "filename" : "icon-72@2x.png", 127 | "scale" : "2x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "icon-76.png", 133 | "scale" : "1x" 134 | }, 135 | { 136 | "size" : "76x76", 137 | "idiom" : "ipad", 138 | "filename" : "icon-76@2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "size" : "83.5x83.5", 143 | "idiom" : "ipad", 144 | "filename" : "icon-83.5@2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "size" : "1024x1024", 149 | "idiom" : "ios-marketing", 150 | "filename" : "icon-1024.png", 151 | "scale" : "1x" 152 | } 153 | ], 154 | "info" : { 155 | "version" : 1, 156 | "author" : "xcode" 157 | } 158 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-1024.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-50.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-57.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-72.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-76.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/g.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "g.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/g.imageset/g.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/g.imageset/g.jpg -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/icon.imageset/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/icon.imageset/icon.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/add.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "add.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "add@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "add@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/add.imageset/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/add.imageset/add.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/add.imageset/add@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/add.imageset/add@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/add.imageset/add@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/add.imageset/add@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/hot.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "hot.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "hot@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "hot@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/hot.imageset/hot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/hot.imageset/hot.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/hot.imageset/hot@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/hot.imageset/hot@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/hot.imageset/hot@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/hot.imageset/hot@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/recommend.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "recommend.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "recommend@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "recommend@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/recommend.imageset/recommend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/recommend.imageset/recommend.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/recommend.imageset/recommend@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/recommend.imageset/recommend@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/recommend.imageset/recommend@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/recommend.imageset/recommend@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/search.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "search.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "search@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "search@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/search.imageset/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/search.imageset/search.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/search.imageset/search@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/search.imageset/search@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/search.imageset/search@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/search.imageset/search@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/setting.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "setting.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "setting@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "setting@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/setting.imageset/setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/setting.imageset/setting.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/setting.imageset/setting@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/setting.imageset/setting@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/setting.imageset/setting@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/setting.imageset/setting@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/tag.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tag.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tag@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tag@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/tag.imageset/tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/tag.imageset/tag.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/tag.imageset/tag@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/tag.imageset/tag@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/tab/tag.imageset/tag@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/Example/Example/Assets.xcassets/tab/tag.imageset/tag@3x.png -------------------------------------------------------------------------------- /Example/Example/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> 3 | <dependencies> 4 | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/> 5 | <capability name="Safe area layout guides" minToolsVersion="9.0"/> 6 | <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> 7 | </dependencies> 8 | <scenes> 9 | <!--View Controller--> 10 | <scene sceneID="EHf-IW-A2E"> 11 | <objects> 12 | <viewController id="01J-lp-oVM" sceneMemberID="viewController"> 13 | <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> 14 | <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> 15 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 16 | <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> 17 | <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> 18 | </view> 19 | </viewController> 20 | <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> 21 | </objects> 22 | <point key="canvasLocation" x="53" y="375"/> 23 | </scene> 24 | </scenes> 25 | </document> 26 | -------------------------------------------------------------------------------- /Example/Example/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView : View { 12 | 13 | var body: some View { 14 | NavigationView { 15 | List { 16 | Section(header: Text("Animation")) { 17 | NavigationLink(destination: LotteryView()) { 18 | PageRow(title: "LotteryView", subTitle: "Rotation Lottery") 19 | } 20 | } 21 | Section(header: Text("特殊视图")) { 22 | NavigationLink(destination: WebViewPage()) { 23 | PageRow(title: "WebView", subTitle: "用于展示一个打开的网页") 24 | } 25 | NavigationLink(destination: ControllerPage<UIKitController>()) { 26 | PageRow(title: "UIViewController", subTitle: "打开 UIViewController") 27 | } 28 | NavigationLink(destination: SpacerPage()) { 29 | PageRow(title: "Spacer", subTitle: "一个空白占用视图,为了方便展示,已用黄色标出") 30 | } 31 | } 32 | Section(header: Text("基础控件")) { 33 | NavigationLink(destination: TextPage()) { 34 | PageRow(title: "Text",subTitle: "显示一行或多行只读文本") 35 | } 36 | NavigationLink(destination: TextFieldPage()) { 37 | PageRow(title: "TextField", subTitle: "显示可编辑文本界面的输入控件") 38 | } 39 | NavigationLink(destination: TextFieldPage()) { 40 | PageRow(title: "SecureField", subTitle: "安全输入私密文本的输入控件") 41 | } 42 | NavigationLink(destination: ImagePage()) { 43 | PageRow(title: "Image",subTitle: "用以展示本地图片") 44 | } 45 | NavigationLink(destination: WebImagePage()) { 46 | PageRow(title: "WebImage",subTitle: "下载网络图片并展示") 47 | } 48 | } 49 | Section(header: Text("按钮")) { 50 | NavigationLink(destination: ButtonPage()) { 51 | PageRow(title: "Button",subTitle: "触发时执行操作的按钮") 52 | } 53 | NavigationLink(destination: NavigationButtonPage()) { 54 | PageRow(title: "NavigationButton",subTitle: "按下时触发导航跳转的按钮") 55 | } 56 | NavigationLink(destination: Text("I'm Text")) { 57 | PageRow(title: "PresentationButton",subTitle: "触发时显示内容的按钮控件") 58 | } 59 | NavigationLink(destination: EditButtonPage()) { 60 | PageRow(title: "EditButton",subTitle: "用于切换当前编辑模式的按钮") 61 | } 62 | } 63 | 64 | Section(header: Text("选择器")) { 65 | NavigationLink(destination: PickerPage()) { 66 | PageRow(title: "Picker",subTitle: "可自定义数据源的 Picker 选择器") 67 | } 68 | NavigationLink(destination: DatePickerPage()) { 69 | PageRow(title: "DatePicker",subTitle: "日期展示与选择") 70 | } 71 | NavigationLink(destination: TogglePage()) { 72 | PageRow(title: "Toggle",subTitle: "开关状态切换") 73 | } 74 | NavigationLink(destination: SliderPage()) { 75 | PageRow(title: "Slider",subTitle: "用以设置指定范围内的值") 76 | } 77 | NavigationLink(destination: StepperPage()) { 78 | PageRow(title: "Stepper",subTitle: "用以增加或减少数值") 79 | } 80 | 81 | } 82 | 83 | Section(header: Text("布局")) { 84 | NavigationLink(destination: HStackPage()) { 85 | PageRow(title: "HStack",subTitle: "将子视图排列在水平线上的视图") 86 | } 87 | NavigationLink(destination: VStackPage()) { 88 | PageRow(title: "VStack",subTitle: "将子视图排列在垂直线上的视图") 89 | } 90 | NavigationLink(destination: ZStackPage()) { 91 | PageRow(title: "ZStack",subTitle: "覆盖子视图,在两轴上对齐") 92 | } 93 | NavigationLink(destination: ListPage()) { 94 | PageRow(title: "List",subTitle: "列表容器,用以显示一列数据") 95 | } 96 | NavigationLink(destination: ScrollViewPage()) { 97 | PageRow(title: "ScrollView",subTitle: "滚动视图") 98 | } 99 | NavigationLink(destination: ForEachPage()) { 100 | PageRow(title: "ForEach",subTitle: "用于根据已有数据的集合展示视图") 101 | } 102 | NavigationLink(destination: GroupPage()) { 103 | PageRow(title: "Group",subTitle: "用于集合多个视图,对 Group 设置的属性,将作用于每个子视图") 104 | }.frame(height: 80) 105 | NavigationLink(destination: SectionPage()) { 106 | PageRow(title: "Section",subTitle: "用于创建带头/尾部的视图内容,一般结合 `List` 组件使用") 107 | }.frame(height: 80) 108 | NavigationLink(destination: FormPage(firstName: "", lastName: "")) { 109 | PageRow(title: "Form",subTitle: "表单视图") 110 | } 111 | } 112 | Section(header: Text("导航视图")) { 113 | NavigationLink(destination: NavigationViewPage()) { 114 | PageRow(title: "NavigationView",subTitle: "用于创建包含顶部导航栏的视图容器") 115 | } 116 | NavigationLink(destination: TableViewPage()) { 117 | PageRow(title: "TabBar",subTitle: "用于创建包含底部 TabBar 的视图容器") 118 | } 119 | } 120 | Section(header: Text("Alert 弹框视图")) { 121 | NavigationLink(destination: AlertPage()) { 122 | PageRow(title: "Alert",subTitle: "展示一个弹框提醒") 123 | } 124 | NavigationLink(destination: ActionSheetPage()) { 125 | PageRow(title: "ActionSheet",subTitle: "弹出一个选择框") 126 | } 127 | NavigationLink(destination: ModalPage()) { 128 | PageRow(title: "Modal",subTitle: "Modal 弹出一个视图") 129 | } 130 | NavigationLink(destination: PopoverPage()) { 131 | PageRow(title: "Popover",subTitle: "Pop 弹出一个视图") 132 | } 133 | } 134 | } 135 | .listStyle(GroupedListStyle()) 136 | .navigationBarTitle(Text("Example"), displayMode: .large) 137 | .navigationBarItems(trailing: Button(action: { 138 | print("Tap") 139 | }, label: { 140 | Text("Right").foregroundColor(.orange) 141 | })) 142 | 143 | } 144 | } 145 | 146 | } 147 | 148 | 149 | #if DEBUG 150 | struct ContentView_Previews : PreviewProvider { 151 | static var previews: some View { 152 | ContentView().colorScheme(.dark) 153 | } 154 | } 155 | #endif 156 | 157 | -------------------------------------------------------------------------------- /Example/Example/Example.entitlements: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>com.apple.security.app-sandbox</key> 6 | <true/> 7 | <key>com.apple.security.network.client</key> 8 | <true/> 9 | </dict> 10 | </plist> 11 | -------------------------------------------------------------------------------- /Example/Example/Extension/Color+Ext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extension.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/10. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | extension Color { 12 | var gradient: AngularGradient { 13 | return AngularGradient(gradient: Gradient(colors: [self]),center: .center) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /Example/Example/Extension/View+Ext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // View+Ext.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/10. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | 12 | extension View { 13 | static var name: String { 14 | return String(describing: self) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Example/Example/Extension/Window+Ext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Window+Ext.swift 3 | // Example 4 | // 5 | // Created by spectatorNan on 2019/8/28. 6 | // Copyright © 2019 Spectator. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | struct MainApp { 12 | 13 | 14 | /// keyWindow 15 | // 'keyWindow' was deprecated in iOS 13.0: Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes 16 | // https://stackoverflow.com/questions/57134259/how-to-resolve-keywindow-was-deprecated-in-ios-13-0 17 | public static var keyWindow: UIWindow? { 18 | return UIApplication.shared.connectedScenes 19 | .filter({$0.activationState == .foregroundActive}) 20 | .map({$0 as? UIWindowScene}) 21 | .compactMap({$0}) 22 | .first?.windows 23 | .filter({$0.isKeyWindow}).first ?? nil 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Example/Example/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>$(DEVELOPMENT_LANGUAGE)</string> 7 | <key>CFBundleExecutable</key> 8 | <string>$(EXECUTABLE_NAME)</string> 9 | <key>CFBundleIdentifier</key> 10 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 11 | <key>CFBundleInfoDictionaryVersion</key> 12 | <string>6.0</string> 13 | <key>CFBundleName</key> 14 | <string>$(PRODUCT_NAME)</string> 15 | <key>CFBundlePackageType</key> 16 | <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> 17 | <key>CFBundleShortVersionString</key> 18 | <string>1.0</string> 19 | <key>CFBundleVersion</key> 20 | <string>1</string> 21 | <key>LSRequiresIPhoneOS</key> 22 | <true/> 23 | <key>NSAppleEventsUsageDescription</key> 24 | <string>AppleEvents Sending Usage Description</string> 25 | <key>UIApplicationSceneManifest</key> 26 | <dict> 27 | <key>UIApplicationSupportsMultipleScenes</key> 28 | <false/> 29 | <key>UISceneConfigurations</key> 30 | <dict> 31 | <key>UIWindowSceneSessionRoleApplication</key> 32 | <array> 33 | <dict> 34 | <key>UILaunchStoryboardName</key> 35 | <string>LaunchScreen</string> 36 | <key>UISceneConfigurationName</key> 37 | <string>Default Configuration</string> 38 | <key>UISceneDelegateClassName</key> 39 | <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> 40 | </dict> 41 | </array> 42 | </dict> 43 | </dict> 44 | <key>UILaunchStoryboardName</key> 45 | <string>LaunchScreen</string> 46 | <key>UIRequiredDeviceCapabilities</key> 47 | <array> 48 | <string>armv7</string> 49 | </array> 50 | <key>UISupportedInterfaceOrientations</key> 51 | <array> 52 | <string>UIInterfaceOrientationPortrait</string> 53 | <string>UIInterfaceOrientationLandscapeLeft</string> 54 | <string>UIInterfaceOrientationLandscapeRight</string> 55 | </array> 56 | <key>UISupportedInterfaceOrientations~ipad</key> 57 | <array> 58 | <string>UIInterfaceOrientationPortrait</string> 59 | <string>UIInterfaceOrientationPortraitUpsideDown</string> 60 | <string>UIInterfaceOrientationLandscapeLeft</string> 61 | <string>UIInterfaceOrientationLandscapeRight</string> 62 | </array> 63 | </dict> 64 | </plist> 65 | -------------------------------------------------------------------------------- /Example/Example/Page/Alert/ActionSheetPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionSheetPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/15. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ActionSheetPage : View { 12 | 13 | @State var showSheet = false 14 | var body: some View { 15 | VStack { 16 | Button(action: { 17 | self.showSheet = true 18 | }) { 19 | Text("ActionSheet") 20 | .bold() 21 | .font(.system(.largeTitle, 22 | design: .rounded)) 23 | } 24 | .actionSheet(isPresented: $showSheet, content: {sheet}) 25 | } 26 | 27 | } 28 | 29 | private var sheet: ActionSheet { 30 | 31 | let action = ActionSheet(title: Text("Title"), 32 | message: Text("Message"), 33 | buttons: 34 | [.default(Text("Default"), action: { 35 | print("Default") 36 | self.showSheet = false 37 | }),.destructive(Text("destructive"), action: { 38 | print("destructive") 39 | self.showSheet = false 40 | }),.cancel({ 41 | print("Cancel") 42 | self.showSheet = false 43 | })]) 44 | 45 | return action 46 | } 47 | } 48 | 49 | #if DEBUG 50 | struct ActionSheetPage_Previews : PreviewProvider { 51 | static var previews: some View { 52 | ActionSheetPage() 53 | } 54 | } 55 | #endif 56 | -------------------------------------------------------------------------------- /Example/Example/Page/Alert/AlertPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct AlertPage : View { 12 | 13 | @State var showAlert = false 14 | 15 | var body: some View { 16 | Button(action: { 17 | self.showAlert = true 18 | print("Tap") 19 | }) { 20 | Text("Click") 21 | .font(.system(size: 40, 22 | design: .rounded)) 23 | } 24 | .alert(isPresented: $showAlert, content: { 25 | Alert(title: Text("确定要支付这100000美元吗?"), 26 | message: Text("请谨慎操作\n一旦确认,钱款将立即转入对方账户"), 27 | primaryButton: .destructive(Text("确认")) { print("已转出") }, 28 | secondaryButton: .cancel()) 29 | }).navigationBarTitle(Text("Alert")) 30 | 31 | } 32 | } 33 | 34 | #if DEBUG 35 | struct AlertPage_Previews : PreviewProvider { 36 | static var previews: some View { 37 | AlertPage() 38 | } 39 | } 40 | #endif 41 | -------------------------------------------------------------------------------- /Example/Example/Page/Alert/ModalPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModalPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/15. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ModalPage : View { 12 | 13 | @State var showModal = false 14 | 15 | var body: some View { 16 | VStack { 17 | Button(action: { 18 | self.showModal = true 19 | }) { 20 | Text("Modal View") 21 | .bold() 22 | .font(.system(.largeTitle, 23 | design: .serif)) 24 | }//.presentation(showModal ? modal:nil) 25 | // .sheet(isPresented: $showModal, content: PickerPage()) 26 | } 27 | } 28 | } 29 | 30 | #if DEBUG 31 | struct ModalPage_Previews : PreviewProvider { 32 | static var previews: some View { 33 | ModalPage() 34 | } 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /Example/Example/Page/Alert/PopoverPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopoverPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/15. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct PopoverPage : View { 12 | 13 | @State var showPop = false 14 | 15 | var body: some View { 16 | VStack { 17 | Button(action: { 18 | self.showPop = true 19 | print(self.showPop) 20 | }) { 21 | Text("Popover").bold().font(.system(.largeTitle, design: .monospaced)) 22 | } 23 | .popover(isPresented: $showPop, content: { 24 | ImagePage() 25 | }) 26 | } 27 | } 28 | } 29 | 30 | #if DEBUG 31 | struct PopoverPage_Previews : PreviewProvider { 32 | static var previews: some View { 33 | PopoverPage() 34 | } 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /Example/Example/Page/Button/ButtonPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Button.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ButtonPage : View { 12 | 13 | var body: some View { 14 | Button(action: { 15 | print("Tap") 16 | }) { 17 | Text("I'm a Button").bold() 18 | .font(.system(size: 40,design: .rounded)) 19 | .shadow(radius: 1) 20 | }.navigationBarTitle(Text("Button")) 21 | } 22 | } 23 | 24 | #if DEBUG 25 | struct ButtonPage_Previews : PreviewProvider { 26 | static var previews: some View { 27 | ButtonPage() 28 | } 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /Example/Example/Page/Button/EditButtonPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EditButtonPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | 12 | struct EditButtonPage : View { 13 | 14 | @ObservedObject private var source = dataSource() 15 | 16 | var body: some View { 17 | List { 18 | 19 | ForEach(source.items, id: \.self) { idx in 20 | PageRow(title: "\(idx)") 21 | } 22 | .onDelete(perform: deletePlace) 23 | .onMove(perform: movePlace) 24 | } 25 | .navigationBarTitle(Text("Edit Row"), displayMode: .large) 26 | .navigationBarItems(trailing: EditButton()) 27 | } 28 | 29 | func deletePlace(at offset: IndexSet) { 30 | if let last = offset.last { 31 | source.items.remove(at: last) 32 | print(source.items.count) 33 | } 34 | } 35 | 36 | func movePlace(from source: IndexSet, to destination: Int) { 37 | print(source,destination) 38 | } 39 | 40 | } 41 | 42 | class dataSource: ObservableObject { 43 | 44 | public var didChange = PassthroughSubject<Void, Never>() 45 | 46 | public var items: [Int] { 47 | didSet { 48 | didChange.send(()) 49 | } 50 | } 51 | 52 | init() { 53 | self.items = (0..<10).map { $0 } 54 | } 55 | } 56 | 57 | 58 | #if DEBUG 59 | struct EditButtonPage_Previews : PreviewProvider { 60 | static var previews: some View { 61 | EditButtonPage() 62 | } 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /Example/Example/Page/Button/NavigationButtonPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationButton.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct NavigationButtonPage : View { 12 | var body: some View { 13 | NavigationLink(destination: NavigationButtonPage()) { 14 | Text("NavigationButton").bold() 15 | .foregroundColor(.orange) 16 | .font(.largeTitle) 17 | } 18 | .navigationBarTitle(Text("Page")) 19 | } 20 | } 21 | 22 | #if DEBUG 23 | struct NavigationButtonPage_Previews : PreviewProvider { 24 | static var previews: some View { 25 | NavigationButtonPage() 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /Example/Example/Page/Container/FormPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FormPage.swift 3 | // Example 4 | // 5 | // Created by Chasel Li on 12/26/19. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct FormPage: View { 12 | 13 | @State var firstName: String 14 | @State var lastName: String 15 | 16 | var body: some View { 17 | VStack { 18 | Form { 19 | TextField("First Name", text: $firstName) 20 | TextField("Last Name", text: $lastName) 21 | } 22 | }.navigationBarTitle(Text("Form")) 23 | 24 | } 25 | } 26 | 27 | struct FormPage_Previews: PreviewProvider { 28 | static var previews: some View { 29 | FormPage(firstName: "", lastName: "") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Example/Example/Page/Container/GroupPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/9. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct GroupPage : View { 12 | 13 | var body: some View { 14 | VStack { 15 | Group { 16 | Text("Hello World !") 17 | Text("Hello World !") 18 | } 19 | .padding(5) 20 | .border(Color.orange.gradient, 21 | width: 1) 22 | .cornerRadius(5) 23 | Group { 24 | Text("Hello World !") 25 | Text("Hello World !") 26 | }.padding(5) 27 | .border(Color.black.gradient, 28 | width: 1) 29 | .cornerRadius(5) 30 | Group { 31 | Text("Hello World !") 32 | Text("Hello World !") 33 | }.padding(5) 34 | .border(Color.purple.gradient, 35 | width: 1) 36 | .cornerRadius(5) 37 | }.navigationBarTitle(Text("Group")) 38 | } 39 | } 40 | 41 | 42 | 43 | #if DEBUG 44 | struct GroupPage_Previews : PreviewProvider { 45 | static var previews: some View { 46 | GroupPage() 47 | } 48 | } 49 | #endif 50 | -------------------------------------------------------------------------------- /Example/Example/Page/Container/SectionPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SectionPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/9. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SectionPage : View { 12 | var body: some View { 13 | 14 | VStack { 15 | List { 16 | Section(header: Text("I'm header"), footer: Text("I'm footer")) { 17 | ForEach(0..<3) { 18 | Text("Hello \($0)") 19 | } 20 | } 21 | Section(header: Text("I'm header 2"), footer: Text("I'm footer 2")) { 22 | ForEach(6..<10) { 23 | Text("Hello \($0)").bold() 24 | } 25 | } 26 | } 27 | .listStyle(GroupedListStyle()) 28 | .background(Color.white) 29 | 30 | Button(action: { 31 | print("Tap") 32 | }) { 33 | Text("SwiftUI") 34 | .foregroundColor(.white) 35 | .frame(width: UIScreen.main.bounds.width - 30,height: 45) 36 | } 37 | .background(Color.orange) 38 | .cornerRadius(5) 39 | 40 | } 41 | .background(Color.white) 42 | .navigationBarTitle(Text("Section")) 43 | 44 | } 45 | } 46 | 47 | #if DEBUG 48 | struct SectionPage_Previews : PreviewProvider { 49 | static var previews: some View { 50 | SectionPage() 51 | } 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /Example/Example/Page/Image/ImagePage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImagePage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ImagePage : View { 12 | 13 | let range = 1..<6 14 | 15 | var body: some View { 16 | VStack { 17 | ForEach(range) { index in 18 | Image("icon") 19 | .resizable() 20 | .frame(width: CGFloat(30 * index), 21 | height: CGFloat(30 * index), 22 | alignment: .center) 23 | .onTapGesture { 24 | print("Tap \(index)") 25 | } 26 | } 27 | }.navigationBarTitle(Text("Image")) 28 | } 29 | } 30 | 31 | #if DEBUG 32 | struct ImagePage_Previews : PreviewProvider { 33 | static var previews: some View { 34 | ImagePage() 35 | } 36 | } 37 | #endif 38 | -------------------------------------------------------------------------------- /Example/Example/Page/Image/WebImagePage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebImagePage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/9. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct WebImagePage : View { 12 | 13 | @State private var uiImage: UIImage? = nil 14 | let placeholderImage = UIImage(named: "icon")! 15 | 16 | var body: some View { 17 | Image(uiImage: self.uiImage ?? placeholderImage) 18 | .resizable() 19 | .onAppear(perform: downloadWebImage) 20 | .frame(width: 80, 21 | height: 80, 22 | alignment: .center) 23 | .onTapGesture { 24 | print("Tap ") 25 | }.navigationBarTitle(Text("WebImage")) 26 | } 27 | 28 | func downloadWebImage() { 29 | 30 | guard let url = URL(string: "https://picsum.photos/50/50?i=30") else { 31 | print("Invalid URL.") 32 | return 33 | } 34 | URLSession.shared.dataTask(with: url) { (data, response, error) in 35 | if let data = data, let image = UIImage(data: data) { 36 | self.uiImage = image 37 | }else { 38 | print("error: \(String(describing: error))") 39 | } 40 | }.resume() 41 | } 42 | } 43 | 44 | #if DEBUG 45 | struct WebImagePage_Previews : PreviewProvider { 46 | static var previews: some View { 47 | WebImagePage() 48 | } 49 | } 50 | #endif 51 | -------------------------------------------------------------------------------- /Example/Example/Page/List/ForEachPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ForEachPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ForEachPage : View { 12 | 13 | let data = (0..<5) 14 | 15 | var body: some View { 16 | ForEach(data) { e in 17 | Text("Hello \(e)") 18 | .bold() 19 | .font(.system(size: 25, design: .monospaced)) 20 | .padding(5) 21 | } 22 | // .border(Color.gray.gradient, width: 1,cornerRadius: 10) 23 | .border(Color.gray.gradient, width: 1) 24 | .cornerRadius(10) 25 | .navigationBarTitle(Text("ForEach")) 26 | } 27 | } 28 | 29 | #if DEBUG 30 | struct ForEachPage_Previews : PreviewProvider { 31 | static var previews: some View { 32 | ForEachPage() 33 | } 34 | } 35 | #endif 36 | -------------------------------------------------------------------------------- /Example/Example/Page/List/ListPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ListPage : View { 12 | var body: some View { 13 | List(0..<30) { item in 14 | Text("Hello World !") 15 | }.navigationBarTitle(Text("List"), displayMode: .large) 16 | } 17 | } 18 | 19 | #if DEBUG 20 | struct ListPage_Previews : PreviewProvider { 21 | static var previews: some View { 22 | ListPage() 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /Example/Example/Page/List/ScrollViewPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollViewPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ScrollViewPage : View { 12 | 13 | var body: some View { 14 | ScrollView { 15 | Text("SwiftUI").padding(20) 16 | Divider() 17 | Image("icon") 18 | .resizable() 19 | .frame(width: 300, height: 300, alignment: .center) 20 | Divider() 21 | Text("Views and controls are the visual building blocks of your app’s user interface.") 22 | } 23 | .border(Color.gray.gradient, width: 1) 24 | .cornerRadius(10) 25 | .padding(10) 26 | .navigationBarTitle(Text("ScrollView")) 27 | } 28 | } 29 | 30 | #if DEBUG 31 | struct ScrollViewPage_Previews : PreviewProvider { 32 | static var previews: some View { 33 | ScrollViewPage() 34 | } 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /Example/Example/Page/Lottery/LotteryControl.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LotteryControl.swift 3 | // Example 4 | // 5 | // Created by xj on 2020/5/8. 6 | // Copyright © 2020 晋先森. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class LotteryControl: ObservableObject { 12 | @Published var rotation = 0.0 13 | let index = 8 14 | var angle: Double { 360 / Double(index) } 15 | 16 | init() { 17 | print("init runed:\(angle)") 18 | Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (timer) in 19 | self.rotation += 30 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Example/Example/Page/Lottery/LotteryView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LotteryView.swift 3 | // Example 4 | // 5 | // Created by xj on 2020/5/8. 6 | // Copyright © 2020 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct LotteryView: View { 12 | 13 | @ObservedObject var control = LotteryControl() 14 | 15 | let colors = [Color.red, .black, .gray, .green, .blue, .orange, .yellow, .purple] 16 | 17 | var body: some View { 18 | ZStack { 19 | ForEach(0..<control.index, id: \.self) { idx in 20 | Path { path in 21 | path.move(to: CGPoint(x: 150, y: 150)) 22 | path.addArc(center: CGPoint(x: 150, y: 150), 23 | radius: 150, 24 | startAngle: Angle(degrees: Double(idx) * self.control.angle), 25 | endAngle: Angle(degrees: Double(idx+1) * self.control.angle), 26 | clockwise: false) 27 | path.addLine(to: CGPoint(x: 150, y: 150)) 28 | }.fill(self.colors[idx%self.colors.count]) 29 | } 30 | }.frame(width: 300, height: 300, 31 | alignment: .center) 32 | .rotationEffect(.degrees(control.rotation)) 33 | } 34 | } 35 | 36 | struct LotteryView_Previews: PreviewProvider { 37 | 38 | static var previews: some View { 39 | LotteryView().frame(width: 300, height: 300, alignment: .center) 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Example/Example/Page/Navigation/NavigationViewPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationViewPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/10. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct NavigationViewPage : View { 12 | var body: some View { 13 | NavigationView { 14 | Text("🧚♂️🧚♀️🧜♂️🧜♀️🧞♂️🧞♀️").blur(radius: 5) 15 | Text("Swifter Swifter") 16 | .bold() 17 | .foregroundColor(.orange) 18 | .font(.largeTitle) 19 | } 20 | .navigationBarTitle(Text("NavigationView")) 21 | .navigationBarItems(trailing: Button(action: { 22 | print("Tap") 23 | }, label: { 24 | Text("Right").foregroundColor(.orange) 25 | })) 26 | 27 | } 28 | } 29 | 30 | #if DEBUG 31 | struct NavigationViewPage_Previews : PreviewProvider { 32 | static var previews: some View { 33 | NavigationViewPage() 34 | } 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /Example/Example/Page/Navigation/TableViewPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabViewPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct TableViewPage : View { 12 | 13 | @State private var index = 0 // 默认选中索引 14 | let imgs = ["hot","recommend","search","tag","setting"] 15 | 16 | var body: some View { 17 | TabView(selection: $index) { 18 | ForEach(0..<imgs.count) { item in 19 | TabItemPage(index: item) 20 | .tabItem{ 21 | Image(self.imgs[item]) 22 | Text("\(item)") 23 | } 24 | .tag(item) 25 | } 26 | }.navigationBarTitle("TabViewPage") 27 | 28 | } 29 | } 30 | 31 | fileprivate struct TabItemPage: View { 32 | 33 | var index: Int 34 | 35 | var body: some View { 36 | ZStack { 37 | Rectangle().foregroundColor(Color.orange) 38 | VStack { 39 | Text("\(index)") 40 | .foregroundColor(.white) 41 | .font(.system(size: 100, design: .rounded)) 42 | .bold() 43 | Image("icon") 44 | .resizable() 45 | .frame(width: 200,height: 200) 46 | } 47 | } 48 | } 49 | } 50 | 51 | 52 | #if DEBUG 53 | struct TableViewPage_Previews : PreviewProvider { 54 | static var previews: some View { 55 | TableViewPage() 56 | } 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /Example/Example/Page/Picker/DatePickerPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PickerPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | struct DatePickerPage : View { 12 | 13 | @ObservedObject var server = DateServer() 14 | 15 | var speaceDate: Range<Date>? 16 | 17 | init() { 18 | let soon = Calendar.current.date(byAdding: .year, 19 | value: -1, 20 | to: server.date) ?? Date() 21 | 22 | let later = Calendar.current.date(byAdding: .year, 23 | value: 1, 24 | to: server.date) ?? Date() 25 | speaceDate = soon..<later 26 | } 27 | 28 | var body: some View { 29 | VStack { 30 | VStack(spacing: 10) { 31 | Text("日期选择").bold() 32 | DatePicker(selection: $server.date, in: server.spaceDate, displayedComponents: .date, label: { 33 | Text("") 34 | }) 35 | } 36 | .padding(.top) 37 | .navigationBarTitle(Text("DatePicker")) 38 | 39 | } 40 | 41 | 42 | } 43 | } 44 | 45 | 46 | class DateServer: ObservableObject { 47 | 48 | var didChange = PassthroughSubject<DateServer,Never>() 49 | var date: Date = Date() { 50 | didSet { 51 | didChange.send(self) 52 | print("Date Changed: \(date)") 53 | } 54 | } 55 | 56 | var spaceDate: ClosedRange<Date> { 57 | let soon = Calendar.current.date(byAdding: .year, 58 | value: -1, 59 | to: date) ?? Date() 60 | 61 | let later = Calendar.current.date(byAdding: .year, 62 | value: 1, 63 | to: date) ?? Date() 64 | let speaceDate = soon...later 65 | return speaceDate 66 | } 67 | } 68 | 69 | 70 | 71 | #if DEBUG 72 | struct DatePickerPage_Previews : PreviewProvider { 73 | static var previews: some View { 74 | DatePickerPage() 75 | } 76 | } 77 | #endif 78 | -------------------------------------------------------------------------------- /Example/Example/Page/Picker/PickerPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PickerPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/12. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct PickerPage : View { 12 | 13 | @State var leftIndex = 0 14 | @State var rightIndex = 0 15 | 16 | let leftSource = (0..<10).map { $0%2 == 0 ? "🧜♀️\($0)":"🧚♀️\($0)" } 17 | let rightSource = (11...36).map { String($0 - 1, radix: $0).uppercased() } 18 | 19 | var body: some View { 20 | HStack { 21 | VStack { 22 | Text("Left Value:") 23 | Text("\(self.leftSource[self.leftIndex])") 24 | .foregroundColor(.orange) 25 | .bold() 26 | .font(.largeTitle) 27 | Picker(selection: $leftIndex, label: Text("Left Picker")) { 28 | ForEach(0..<leftSource.count) { 29 | Text(self.leftSource[$0]).tag($0) 30 | } 31 | }.frame(width: UIScreen.main.bounds.width/2) 32 | } 33 | VStack { 34 | Text("Right Value:") 35 | Text("\(self.rightSource[self.rightIndex])") 36 | .foregroundColor(.black) 37 | .bold() 38 | .font(.largeTitle) 39 | Picker(selection: $rightIndex, label: Text("Right Picker")) { 40 | ForEach(0..<rightSource.count) { 41 | Text(self.rightSource[$0]).tag($0) 42 | } 43 | }.frame(width: UIScreen.main.bounds.width/2) 44 | } 45 | } 46 | .navigationBarTitle(Text("Picker")) 47 | } 48 | } 49 | 50 | #if DEBUG 51 | struct PickerPage_Previews : PreviewProvider { 52 | static var previews: some View { 53 | PickerPage() 54 | } 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /Example/Example/Page/Picker/SegmentedControlPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SegmentedControlPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | 12 | // SegmentedControl is deprecated 13 | // https://developer.apple.com/documentation/swiftui/segmentedcontrol 14 | /* 15 | struct SegmentedControlPage : View { 16 | 17 | @State var items = (0..<5).map { "Seg \($0)" } 18 | @State var currentIndex = 0 19 | 20 | var body: some View { 21 | VStack { 22 | Text("SegmentedControl") 23 | SegmentedControlPage(items: <#T##[String]#>, currentIndex: <#T##Int#>) 24 | 25 | SegmentedControl(selection: $currentIndex) { 26 | ForEach(0..<items.count) { index in 27 | Text(self.items[index]).tag(index) 28 | } 29 | }.onTapGesture { 30 | print("currentIndex: \(self.currentIndex)") 31 | } 32 | } 33 | } 34 | } 35 | 36 | #if DEBUG 37 | struct SegmentedControlPage_Previews : PreviewProvider { 38 | static var previews: some View { 39 | SegmentedControlPage() 40 | } 41 | } 42 | #endif 43 | */ 44 | -------------------------------------------------------------------------------- /Example/Example/Page/Picker/SliderPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SliderPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | 12 | struct SliderPage : View { 13 | 14 | @State var rating = 0.5 15 | 16 | var body: some View { 17 | VStack { 18 | Text("Slider Value: \(self.rating)") 19 | Slider(value: $rating) 20 | .padding(30) 21 | 22 | }.navigationBarTitle(Text("Slider")) 23 | } 24 | } 25 | 26 | 27 | 28 | #if DEBUG 29 | struct SliderPage_Previews : PreviewProvider { 30 | static var previews: some View { 31 | SliderPage() 32 | } 33 | } 34 | #endif 35 | -------------------------------------------------------------------------------- /Example/Example/Page/Picker/StepperPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StepperPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | 12 | struct StepperPage : View { 13 | 14 | @State var value = 0 15 | 16 | var body: some View { 17 | HStack { 18 | Stepper(value: $value, step: 2, onEditingChanged: { c in 19 | print(c) 20 | }) { 21 | Text("Stepper Value: \(self.value)") 22 | }.padding(50) 23 | }.navigationBarTitle(Text("Stepper")) 24 | } 25 | } 26 | 27 | #if DEBUG 28 | struct StepperPage_Previews : PreviewProvider { 29 | static var previews: some View { 30 | StepperPage() 31 | } 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /Example/Example/Page/Picker/TogglePage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TogglePage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | struct TogglePage : View { 12 | 13 | @State var isOn = false 14 | 15 | var body: some View { 16 | HStack { 17 | Toggle(isOn: $isOn) { 18 | Text("State: \(self.isOn == true ? "开":"关")") 19 | }.padding(20) 20 | Spacer() 21 | }.navigationBarTitle(Text("Toggle")) 22 | } 23 | } 24 | 25 | #if DEBUG 26 | struct TogglePage_Previews : PreviewProvider { 27 | static var previews: some View { 28 | TogglePage() 29 | } 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /Example/Example/Page/SpecialPage/ControllerPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MakeUIView.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/13. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import UIKit 12 | 13 | struct ControllerPage<T: UIViewController> : UIViewControllerRepresentable { 14 | 15 | typealias UIViewControllerType = UIViewController 16 | 17 | func makeUIViewController(context: UIViewControllerRepresentableContext<ControllerPage>) -> UIViewController { 18 | return T() 19 | } 20 | 21 | func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ControllerPage>) { 22 | debugPrint("\(#function):\(type(of: T.self))") 23 | } 24 | 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/Example/Page/SpecialPage/SpacerPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SpacerPage.swift 3 | // Example 4 | // 5 | // Created by likeecat on 2022/11/25. 6 | // Copyright © 2022 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SpacerPage: View { 12 | var body: some View { 13 | VStack{ 14 | HStack { 15 | Text("made in China.") 16 | Spacer().frame(height: 20).background(Color.yellow) 17 | Text("the People's Republic Of China.") 18 | } 19 | Divider() // Just add a line. 20 | VStack { 21 | Text("made in China.") 22 | Spacer().frame(width: 20).background(Color.yellow) 23 | Text("the People's Republic Of China.") 24 | } 25 | } 26 | } 27 | } 28 | 29 | struct SpacerPage_Previews: PreviewProvider { 30 | static var previews: some View { 31 | SpacerPage() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Example/Example/Page/SpecialPage/UIKitController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OKController.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/13. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import SwiftUI 12 | 13 | class UIKitController: UIViewController { 14 | 15 | override func viewDidLoad() { 16 | 17 | view.addSubview(button) 18 | 19 | } 20 | 21 | lazy var button: UIButton = { 22 | let button = UIButton(type: .system) 23 | button.setTitle("Open SwiftUI View", for: .normal) 24 | button.titleLabel?.font = .boldSystemFont(ofSize: 30) 25 | button.setTitleColor(.orange, for: .normal) 26 | button.sizeToFit() 27 | button.center = view.center 28 | button.addTarget(self, action: #selector(openContentView), 29 | for: .touchUpInside) 30 | return button 31 | }() 32 | 33 | @objc func openContentView() { 34 | 35 | let hostVC = UIHostingController(rootView: ContentView()) 36 | present(hostVC, animated: true, completion: nil) 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Example/Example/Page/SpecialPage/WebViewPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import WebKit 11 | 12 | struct WebViewPage : UIViewRepresentable { 13 | func makeUIView(context: Context) -> WKWebView { 14 | return WKWebView() 15 | } 16 | func updateUIView(_ uiView: WKWebView, context: Context) { 17 | let req = URLRequest(url: URL(string: "https://www.apple.com")!) 18 | uiView.load(req) 19 | } 20 | } 21 | 22 | #if DEBUG 23 | struct WebViewPage_Previews : PreviewProvider { 24 | static var previews: some View { 25 | WebViewPage() 26 | } 27 | } 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /Example/Example/Page/Stack/HStackPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HStackPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct HStackPage : View { 12 | var body: some View { 13 | HStack { 14 | Text("made in China.") 15 | Divider() // Just add a line. 16 | Text("the People's Republic Of China.") 17 | } 18 | } 19 | } 20 | 21 | #if DEBUG 22 | struct HStackPage_Previews : PreviewProvider { 23 | static var previews: some View { 24 | HStackPage() 25 | } 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /Example/Example/Page/Stack/VStackPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VStackPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct VStackPage : View { 12 | var body: some View { 13 | VStack { 14 | Text("made in China.") 15 | Divider() // Just add a line. 16 | Text("the People's Republic Of China.") 17 | } 18 | } 19 | } 20 | 21 | #if DEBUG 22 | struct VStackPage_Previews : PreviewProvider { 23 | static var previews: some View { 24 | VStackPage() 25 | } 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /Example/Example/Page/Stack/ZStackPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZStackPage.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/8. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ZStackPage : View { 12 | var body: some View { 13 | ZStack { 14 | Text("made in China.") 15 | Divider() // Just add a line. 16 | Text("the People's Republic Of China.") 17 | } 18 | } 19 | } 20 | 21 | #if DEBUG 22 | struct ZStackPage_Previews : PreviewProvider { 23 | static var previews: some View { 24 | ZStackPage() 25 | } 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /Example/Example/Page/Text/TextFieldPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextField.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct TextFieldPage : View { 12 | 13 | @State var name: String = "" 14 | @State var password: String = "" 15 | 16 | let nameText = Text("请填入昵称").foregroundColor(.secondary).font(.system(size: 16)) 17 | let pwdText = Text("请填入密码").foregroundColor(.secondary).font(.system(size: 16)) 18 | 19 | var body: some View { 20 | VStack(spacing: 15) { 21 | HStack { 22 | Text("昵称:") 23 | .foregroundColor(.secondary) 24 | 25 | TextField("", text: $name, onEditingChanged: { (changed) in 26 | print("onEditing: \(changed)") 27 | }, onCommit: { 28 | print("userName: \(self.name)") 29 | self.endEditing(true) 30 | }) 31 | }.padding(10).frame(height: 50).textFieldStyle(RoundedBorderTextFieldStyle()) 32 | .padding(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) 33 | 34 | HStack { 35 | Text("密码:").foregroundColor(.secondary) 36 | SecureField("", text: $password) { 37 | print("Password: \(self.password)") 38 | self.endEditing(true) 39 | } 40 | }.padding(10) 41 | .frame(height: 50) 42 | .textFieldStyle(RoundedBorderTextFieldStyle()) 43 | .padding(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) 44 | }.offset(y: -150) 45 | .navigationBarTitle(Text("TextField")) 46 | 47 | } 48 | 49 | private func endEditing(_ force: Bool) { 50 | // UIApplication.shared.keyWindow?.endEditing(force) 51 | MainApp.keyWindow?.endEditing(force) 52 | } 53 | } 54 | 55 | // https://stackoverflow.com/questions/56491386/how-to-hide-keyboard-when-using-swiftui 56 | 57 | 58 | #if DEBUG 59 | struct TextFieldPage_Previews : PreviewProvider { 60 | static var previews: some View { 61 | TextFieldPage() 62 | } 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /Example/Example/Page/Text/TextPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Text.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | private let github = "https://github.com/Jinxiansen/SwiftUI" 12 | 13 | struct TextPage : View { 14 | 15 | var body: some View { 16 | VStack(spacing: 15) { 17 | Text("SwiftUI") 18 | Text("SwiftUI") 19 | .foregroundColor(.orange) 20 | .bold() 21 | .font(.system(.largeTitle)) 22 | .fontWeight(.medium) 23 | .italic() 24 | .shadow(color: .black, radius: 1, x: 0, y: 2) 25 | 26 | Text(github) 27 | .underline(true, color: Color.gray) 28 | .font(.system(size: 16, design: .serif)).onTapGesture { 29 | print(github) 30 | } 31 | 32 | HStack { 33 | Text("Text") 34 | Text("TextField").bold() 35 | Text("SecureField").foregroundColor(.orange) 36 | } 37 | 38 | Text("Views and controls are the visual building blocks of your app’s user interface." + 39 | " Use them to present your app’s content onscreen.") 40 | .lineLimit(nil) 41 | } 42 | } 43 | } 44 | 45 | #if DEBUG 46 | struct TextPage_Previews : PreviewProvider { 47 | static var previews: some View { 48 | TextPage() 49 | } 50 | } 51 | #endif 52 | -------------------------------------------------------------------------------- /Example/Example/PageRow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageRow.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct PageRow : View { 12 | 13 | private let title: String 14 | private let subTitle: String? 15 | 16 | init(title: String,subTitle: String? = nil) { 17 | self.title = title 18 | self.subTitle = subTitle 19 | } 20 | 21 | var body: some View { 22 | VStack(alignment: .leading, spacing: 5) { 23 | Text(title).bold() 24 | if subTitle != nil { 25 | Text(subTitle!).font(.subheadline).opacity(0.5).lineLimit(nil) 26 | } 27 | } 28 | } 29 | 30 | } 31 | 32 | #if DEBUG 33 | struct PageRow_Previews : PreviewProvider { 34 | static var previews: some View { 35 | PageRow(title: "一条数据") 36 | } 37 | } 38 | #endif 39 | -------------------------------------------------------------------------------- /Example/Example/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Example/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // Example 4 | // 5 | // Created by 晋先森 on 2019/6/7. 6 | // Copyright © 2019 晋先森. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | if let windowScene = scene as? UIWindowScene { 19 | let window = UIWindow(windowScene: windowScene) 20 | window.rootViewController = UIHostingController(rootView: ContentView()) 21 | self.window = window 22 | window.makeKeyAndVisible() 23 | } 24 | } 25 | 26 | func sceneDidDisconnect(_ scene: UIScene) { 27 | 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | 32 | } 33 | 34 | func sceneWillResignActive(_ scene: UIScene) { 35 | 36 | } 37 | 38 | func sceneWillEnterForeground(_ scene: UIScene) { 39 | 40 | } 41 | 42 | func sceneDidEnterBackground(_ scene: UIScene) { 43 | 44 | } 45 | 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 晋先森: hi@jinxiansen.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | <img src="images/icon/banner.png"/> 2 | 3 | [](https://github.com/Jinxiansen/SwiftUI) 4 | [](https://swift.org) 5 | [](https://developer.apple.com/xcode) 6 | [](https://developer.apple.com/macOS) 7 | [](https://opensource.org/licenses/MIT) 8 | 9 | 10 | This article refers to SwiftUI [apple example](https://github.com/Jinxiansen/SwiftUI/tree/doc) and records the results of the exploration here, I hope to be helpful to you. 11 | 12 | For the content described in this article, by default you have some experience based on Swift language development, so it will not describe every detail in detail; if you have doubts about Swift syntax, you can learn [Swift](https://swift.org) Grammar. 13 | 14 | When learning and using `SwiftUI`, if you have any questions, you can join the SwiftUI QQ Group: **18552966** to discuss communication. 15 | 16 | [中文版🇨🇳](README_CN.md) 17 | 18 | > Recommended Preview: [Windows 11](https://github.com/Jinxiansen/Windows11) desktop client implemented using **SwiftUI**. 19 | > 20 | > <img width="80%" src="images/windows11/launchpad.png"/> 21 | 22 | 23 | ### ⭐️ Stargazers over time 24 | 25 | [](https://starchart.cc/Jinxiansen/SwiftUI) 26 | 27 | ### 💻 Requirements 28 | 29 | - macOS 10.15 30 | - Xcode 11.0 31 | - iOS 13.0 32 | 33 | 34 | ## Directory: 35 | 36 | ### Basic View 37 | 38 | * <span id="Text_D">Text</span> 39 | - [Text](#Text) 40 | - [TextField](#TextField) 41 | - [SecureField](#SecureField) 42 | 43 | * <span id="Image_D">Image</span> 44 | - [Image](#Image) 45 | - [WebImage](#WebImage) 46 | 47 | * <span id="Button_D">Button</span> 48 | - [Button](#Button) 49 | - [PullDownButton](#PullDownButton) 50 | - [ItemBasedPopUpButton](#ItemBasedPopUpButton) 51 | - [NavigationButton](#NavigationButton) 52 | - [PresentationButton](#PresentationButton) 53 | - [EditButton](#EditButton) 54 | - [PasteButton](#PasteButton) 55 | 56 | * <span id="Picker_D">Picker</span> 57 | - [Picker](#Picker) 58 | - [DatePicker](#DatePicker) 59 | - [Toggle](#Toggle) 60 | - [Slider](#Slider) 61 | - [Stepper](#Stepper) 62 | - [SegmentedControl](#SegmentedControl) 63 | 64 | * <span id="Special_D">Special Views</span> 65 | - [WebView](#WebView) 66 | - [UIViewController](#UIViewController) 67 | 68 | ### <span id="Layout_D">Layout</span> 69 | 70 | * <span id="Stacks_D">Stacks</span> 71 | - [HStack](#HStack) 72 | - [VStack](#VStack) 73 | - [ZStack](#ZStack) 74 | 75 | * <span id="List_D">List</span> 76 | - [List](#List) 77 | - [ScrollView](#ScrollView) 78 | - [ForEach](#ForEach) 79 | 80 | * <span id="Container_D">Container Views</span> 81 | - [Group](#Group) 82 | - [GroupBox](#GroupBox) 83 | - [Section](#Section) 84 | - [Form](#Form) 85 | 86 | * <span id="Architectural_D">Architectural Views</span> 87 | - [NavigationView](#NavigationView) 88 | - [TabView](#TabView) 89 | - [HSplitView](#HSplitView) 90 | - [VSplitView](#VSplitView) 91 | 92 | * <span id="Alert_D"> Alert </span> 93 | - [Alert](#Alert) 94 | - [Modal](#Modal) 95 | - [Popover](#Popover) 96 | - [Sheet](#Sheet) 97 | - [ActionSheet](#ActionSheet) 98 | 99 | 100 | ### <span id="State_D">State and Data Flow</span> 101 | 102 | * <span id="Bindings_D"> Bindings </span> 103 | * [Binding](#Binding) 104 | 105 | * <span id="Data_D"> Data-Dependent Views </span> 106 | * [State](#State) 107 | * [ObjectBinding](#ObjectBinding) 108 | * [EnvironmentObject](#EnvironmentObject) 109 | 110 | * <span id="Environment_D"> Environment Values </span> 111 | * [Environment](#Environment) 112 | * [EnvironmentValues](#EnvironmentValues) 113 | 114 | * <span id="ENavigation_D"> ENavigation Models </span> 115 | * [DynamicNavigationDestinationLink](#DynamicNavigationDestinationLink) 116 | 117 | * <span id="Preferences_D"> Preferences </span> 118 | * [LocalizedStringKey](#LocalizedStringKey) 119 | 120 | * <span id="Transactions_D"> Transactions </span> 121 | * [Transaction](#Transaction) 122 | 123 | 124 | ### <span id="Gestures_D">Gestures</span> 125 | 126 | * <span id="BasicGestures_D"> Basic Gestures </span> 127 | * [TapGesture](#TapGesture) 128 | * [LongPressGesture](#LongPressGesture) 129 | * [DragGesture](#DragGesture) 130 | * [MagnificationGesture](#MagnificationGesture) 131 | * [RotationGesture](#RotationGesture) 132 | 133 | * <span id="Combined_D"> Combined Gestures </span> 134 | * [SequenceGesture](#SequenceGesture) 135 | * [SimultaneousGesture](#SimultaneousGesture) 136 | * [ExclusiveGesture](#ExclusiveGesture) 137 | 138 | * <span id="Custom_D"> Custom Gestures </span> 139 | * [AnyGesture](#AnyGesture) 140 | 141 | 142 | <h2 id="Basic View">Basic View</h2> 143 | 144 | 145 | <h4 id="Text">Text</h4> 146 | 147 | `Text` is used to display one or more lines of text content with the same effect as `UILabel`, but it is even better. 148 | 149 | If you want to create `Text`, just create it with `Text("SwiftUI")`; 150 | With chained syntax, you can also add multiple attributes to the text, such as fonts, colors, shadows, spacing between top left and right, and so on. 151 | 152 | Example: 153 | 154 | ```swift 155 | 156 | Text("SwiftUI") 157 | .foregroundColor(.orange) 158 | .bold() 159 | .font(.system(.largeTitle)) 160 | .fontWeight(.medium) 161 | .italic() 162 | .shadow(color: .black, radius: 1, x: 0, y: 2) 163 | 164 | ``` 165 | 166 | <details close> 167 | <summary>View running results</summary> 168 | <img width="80%" src="images/example/Text.png"/> 169 | </details> 170 | 171 | 172 | > HStack and VStack controls are used to host multiple views, as mentioned later. 173 | 174 | [🔝](#Text_D) 175 | 176 | <h4 id="TextField"> TextField </h4> 177 | 178 | `TextField` is used to add a normal input box, which is often used as a text input. 179 | 180 | Example: 181 | 182 | ```swift 183 | 184 | TextField(self.$name, placeholder: self.nameText, onEditingChanged: { changed in 185 | print("onEditing: \(changed)") 186 | }) { 187 | print("userName: \(self.name)") 188 | self.endEditing(true) 189 | }} 190 | .padding(10) 191 | .frame(height: 50) 192 | .textFieldStyle(RoundedBorderTextFieldStyle()) 193 | .padding(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) 194 | 195 | ``` 196 | 197 | <details close> 198 | <summary>View running results</summary> 199 | <img width="80%" src="images/example/Field.png"/> 200 | </details> 201 | 202 | [🔝](#Text_D) 203 | 204 | <h4 id="SecureField"> SecureField </h4> 205 | 206 | `SecureField ` is generally used as a password input. It is used in the same way as `TextField`. The example and the running effect are the same as `TextField`. 207 | 208 | 209 | <h4 id="Image"> Image </h4> 210 | 211 | The `Image` control is used to display images, example: 212 | 213 | ```swift 214 | 215 | Image("icon") 216 | .resizable() 217 | .frame(width: 100, 218 | height: 100, 219 | alignment: .center) 220 | 221 | ``` 222 | 223 | <details close> 224 | <summary>View running results</summary> 225 | <img width="80%" src="images/example/Image.png"/> 226 | </details> 227 | 228 | [🔝](#Text_D) 229 | 230 | <h4 id="WebImage"> WebImage </h4> 231 | 232 | `webImage` is used to download the web image, use the `URLSession` to download the original `Image` after successful download; you can also use [Kingfisher]((https://github.com/onevcat/Kingfisher)) in the `downloadWebImage ` function . 233 | 234 | Example: 235 | 236 | ```swift 237 | 238 | var body: some View { 239 | Image(uiImage: self.uiImage ?? placeholderImage) 240 | .resizable() 241 | .onAppear(perform: downloadWebImage) 242 | .frame(width: 80, 243 | height: 80, 244 | alignment: .center) 245 | .onTapGesture { 246 | print("Tap ") 247 | } 248 | } 249 | 250 | ``` 251 | 252 | <details close> 253 | <summary>View running results</summary> 254 | <img width="80%" src="images/example/WebImage.png"/> 255 | </details> 256 | 257 | [🔝](#Text_D) 258 | 259 | <h4 id="Button"> Button </h4> 260 | 261 | `Button` is used to respond to click events. 262 | 263 | Example: 264 | 265 | ```swift 266 | 267 | Button(action: { 268 | print("Tap") 269 | }) { 270 | Text("I'm a Button") 271 | } 272 | 273 | ``` 274 | <details close> 275 | <summary>View running results</summary> 276 | <img width="80%" src="images/example/Button.png"/> 277 | </details> 278 | 279 | [🔝](#Button_D) 280 | 281 | <h4 id="PullDownButton"> PullDownButton </h4> 282 | 283 | Waiting for release. 284 | 285 | <h4 id="ItemBasedPopUpButton"> ItemBasedPopUpButton </h4> 286 | 287 | Waiting for release. 288 | 289 | 290 | <h4 id="NavigationButton"> NavigationButton </h4> 291 | 292 | `NavigationButtonPage ` is used to push to the next navigation page. 293 | 294 | Example: 295 | 296 | ```swift 297 | 298 | NavigationLink(destination: NavigationButtonPage()) { 299 | Text("NavigationButton").bold() 300 | .foregroundColor(.orange) 301 | .font(.largeTitle) 302 | } 303 | .navigationBarTitle(Text("Page")) 304 | 305 | ``` 306 | 307 | <details close> 308 | <summary>View running results</summary> 309 | <img width="80%" src="images/example/NavigationButton.png"/> 310 | </details> 311 | 312 | [🔝](#Button_D) 313 | 314 | <h4 id="PresentationButton" style='color:red'> PresentationButton is deprecated</h4> 315 | 316 | `PresentationButton` ~~is used to pop up a page.~~ has deprecated, please use `NavigationLink` 317 | 318 | 319 | [🔝](#Button_D) 320 | 321 | <h4 id="EditButton"> EditButton </h4> 322 | 323 | `EditButton` is used to trigger the editing state, just use the `navigationBarItems` setting when using it. 324 | 325 | Example: 326 | 327 | ```swift 328 | 329 | navigationBarItems(trailing: EditButton()) 330 | 331 | ``` 332 | 333 | <details close> 334 | <summary>View running results</summary> 335 | <img width="80%" src="images/example/EditButton.png"/> 336 | </details> 337 | 338 | [🔝](#Button_D) 339 | 340 | <h4 id="PasteButton"> PasteButton </h4> 341 | 342 | Waiting for release. 343 | 344 | 345 | <h4 id="Picker"> Picker </h4> 346 | 347 | `Picker` can customize the selector of the data source. 348 | 349 | Example: 350 | 351 | ```swift 352 | 353 | Picker(selection: $leftIndex, label: Text("Picker")) { 354 | ForEach(0..<leftSource.count) { 355 | Text(self.leftSource[$0]).tag($0) 356 | } 357 | }.frame(width: UIScreen.main.bounds.width/2) 358 | 359 | ``` 360 | 361 | <details close> 362 | <summary>View running results</summary> 363 | <img width="80%" src="images/example/Picker.png"/> 364 | </details> 365 | 366 | [🔝](#Picker_D) 367 | 368 | <h4 id="DatePicker"> DatePicker </h4> 369 | 370 | `DatePicker` is used to select the absolute date of the control. 371 | 372 | Example: 373 | 374 | ```swift 375 | 376 | DatePicker(selection: $server.date, 377 | in: server.spaceDate, 378 | displayedComponents: .date, label: { 379 | Text("") 380 | }) 381 | 382 | ``` 383 | 384 | <details close> 385 | <summary>View running results</summary> 386 | <img width="80%" src="images/example/DatePicker.png"/> 387 | </details> 388 | 389 | [🔝](#Picker_D) 390 | 391 | <h4 id="Toggle"> Toggle </h4> 392 | 393 | `Toggle` is used to switch the selected state, for example: 394 | 395 | ```swift 396 | 397 | Toggle(isOn: $isOn) { 398 | Text("State: \(self.isOn == true ? "Open":"open")") 399 | }.padding(20) 400 | 401 | ``` 402 | 403 | <details close> 404 | <summary>View running results</summary> 405 | <img width="80%" src="images/example/Toggle.png"/> 406 | </details> 407 | 408 | [🔝](#Picker_D) 409 | 410 | <h4 id="Slider"> Slider </h4> 411 | 412 | `Slider ` A control for selecting values from a finite range of values, example: 413 | 414 | ```swift 415 | 416 | Slider(value: $data.rating) 417 | 418 | ``` 419 | 420 | <details close> 421 | <summary>View running results</summary> 422 | <img width="80%" src="images/example/Slider.png"/> 423 | </details> 424 | 425 | [🔝](#Picker_D) 426 | 427 | <h4 id="Stepper"> Stepper </h4> 428 | 429 | `Stepper ` is used to increase or decrease the value, example: 430 | 431 | ```swift 432 | 433 | Stepper(value: $value, step: 2, onEditingChanged: { c in 434 | print(c) 435 | }) { 436 | Text("Stepper Value: \(self.value)") 437 | }.padding(50) 438 | 439 | ``` 440 | 441 | <details close> 442 | <summary>View running results</summary> 443 | <img width="80%" src="images/example/Stepper.png"/> 444 | </details> 445 | 446 | [🔝](#Picker_D) 447 | 448 | <h4 id="SegmentedControl" style="color:red">SegmentedControl is deprecated</h4> 449 | 450 | `SegmentedControl ` is used for segmentation condition selection, example: 451 | 452 | ```swift 453 | 454 | SegmentedControl(selection: $currentIndex) { 455 | ForEach(0..<items.count) { index in 456 | Text(self.items[index]).tag(index) 457 | } 458 | }.tapAction { 459 | print("currentIndex: \(self.currentIndex)") 460 | } 461 | 462 | ``` 463 | 464 | <details close> 465 | <summary>View running results</summary> 466 | <img width="80%" src="images/example/SegmentedControl.png"/> 467 | </details> 468 | 469 | [🔝](#Picker_D) 470 | 471 | <h4 id="WebView"> WebView </h4> 472 | 473 | `WebView` is used to display an open web page, example: 474 | 475 | ```swift 476 | 477 | struct WebViewPage : UIViewRepresentable { 478 | func makeUIView(context: Context) -> WKWebView { 479 | return WKWebView() 480 | } 481 | func updateUIView(_ uiView: WKWebView, context: Context) { 482 | let req = URLRequest(url: URL(string: "https://www.apple.com")!) 483 | uiView.load(req) 484 | } 485 | } 486 | 487 | ``` 488 | 489 | <details close> 490 | <summary>View running results</summary> 491 | <img width="80%" src="images/example/WebView.png"/> 492 | </details> 493 | 494 | [🔝](#Special_D) 495 | 496 | <h4 id="UIViewController"> UIViewController </h4> 497 | 498 | `UIViewController` is used to display the **UIViewController** that opens **UIKit** in **SwiftUI** and opens the `SwiftUI` View in **UIViewController**. 499 | 500 | Example: 501 | 502 | First define: 503 | 504 | ```swift 505 | 506 | struct ControllerPage<T: UIViewController> : UIViewControllerRepresentable { 507 | 508 | typealias UIViewControllerType = UIViewController 509 | 510 | func makeUIViewController(context: UIViewControllerRepresentableContext<ControllerPage>) -> UIViewController { 511 | return T() 512 | } 513 | 514 | func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ControllerPage>) { 515 | debugPrint("\(#function):\(type(of: T.self))") 516 | } 517 | 518 | } 519 | 520 | ``` 521 | 522 | Then use this: 523 | 524 | ```swift 525 | 526 | NavigationButton(destination: ControllerPage<UIKitController>()) { 527 | PageRow(title: "UIViewController",subTitle: "Open UIViewController") 528 | 529 | } 530 | 531 | ``` 532 | 533 | 534 | <details close> 535 | <summary>View running results</summary> 536 | <img width="80%" src="images/example/UIViewController.png"/> 537 | <img width="80%" src="images/example/UIViewController2.png"/> 538 | </details> 539 | 540 | [🔝](#Special_D) 541 | 542 | 543 | ### Layout 544 | 545 | 546 | <h4 id="HStack"> HStack </h4> 547 | 548 | `HStack` is used to arrange the subviews on a horizontal line. 549 | 550 | Example: 551 | 552 | ```swift 553 | 554 | HStack { 555 | Text("made in China.") 556 | Divider() // Just add a line. 557 | Text("the People's Republic Of China.") 558 | } 559 | 560 | ``` 561 | 562 | <details close> 563 | <summary>View running results</summary> 564 | <img width="80%" src="images/example/HStack.png"/> 565 | </details> 566 | 567 | [🔝](#Layout_D) 568 | 569 | <h4 id="VStack"> VStack </h4> 570 | 571 | `VStack` is used to arrange the subviews on a vertical line. 572 | 573 | Example: 574 | 575 | ```swift 576 | 577 | VStack { 578 | Text("made in China.") 579 | Divider() // Just add a line. 580 | Text("the People's Republic Of China.") 581 | } 582 | 583 | ``` 584 | 585 | <details close> 586 | <summary>View running results</summary> 587 | <img width="80%" src="images/example/VStack.png"/> 588 | </details> 589 | 590 | [🔝](#Layout_D) 591 | 592 | <h4 id="ZStack"> ZStack </h4> 593 | 594 | `ZStack` is used to override the subview, aligned on two axes. 595 | 596 | Example: 597 | 598 | ```swift 599 | 600 | ZStack { 601 | Text("made in China.") 602 | Divider() // Just add a line. 603 | Text("the People's Republic Of China.") 604 | } 605 | 606 | ``` 607 | 608 | <details close> 609 | <summary>View running results</summary> 610 | <img width="80%" src="images/example/ZStack.png"/> 611 | </details> 612 | 613 | [🔝](#Layout_D) 614 | 615 | <h4 id="List"> List </h4> 616 | 617 | `List` list container to display a list of data. 618 | 619 | Examples: 620 | 621 | ```swift 622 | 623 | List(0..<5) { item in 624 | Text("Hello World !") 625 | }.navigationBarTitle(Text("List"), displayMode: .large) 626 | 627 | ``` 628 | 629 | <details close> 630 | <summary>View running results</summary> 631 | <img width="80%" src="images/example/List.png"/> 632 | </details> 633 | 634 | [🔝](#Layout_D) 635 | 636 | <h4 id="ScrollView"> ScrollView </h4> 637 | 638 | `ScrollView` is a scroll view container. 639 | 640 | Example: 641 | 642 | ```swift 643 | 644 | ScrollView { 645 | Text("SwiftUI").padding(20) 646 | Divider() 647 | Image("icon").resizable() 648 | .frame(width: 300, height: 300, alignment: .center) 649 | Divider() 650 | Text("Views and ... user interface.") 651 | } 652 | .border(Color.gray.gradient, width: 1) 653 | .cornerRadius(10) 654 | .padding(10) 655 | .navigationBarTitle(Text("ScrollView")) 656 | 657 | ``` 658 | 659 | <details close> 660 | <summary>View running results</summary> 661 | <img width="80%" src="images/example/ScrollView.png"/> 662 | </details> 663 | 664 | [🔝](#Layout_D) 665 | 666 | <h4 id="ForEach"> ForEach </h4> 667 | 668 | `ForEach` is used to present a view based on a collection of existing data. 669 | 670 | Example: 671 | 672 | ```swift 673 | 674 | let data = (0..<5) 675 | var body: some View { 676 | ForEach(data) { e in 677 | Text("Hello \(e)") 678 | .bold() 679 | .font(.system(size: 25, design: .monospaced)) 680 | .padding(5) 681 | } 682 | 683 | ``` 684 | 685 | <details close> 686 | <summary>View running results</summary> 687 | <img width="80%" src="images/example/ForEach.png"/> 688 | </details> 689 | 690 | [🔝](#Layout_D) 691 | 692 | <h4 id="Group"> Group </h4> 693 | 694 | `Group` is used to aggregate multiple views, and the properties set on the Group will be applied to each child view. 695 | 696 | Example: 697 | 698 | ```swift 699 | 700 | Group { 701 | Text("Hello World !") 702 | Text("Hello World !") 703 | } 704 | 705 | ``` 706 | 707 | <details close> 708 | <summary>View running results</summary> 709 | <img width="80%" src="images/example/Group.png"/> 710 | </details> 711 | 712 | [🔝](#Layout_D) 713 | 714 | <h4 id="GroupBox"> GroupBox </h4> 715 | 716 | Waiting for release. 717 | 718 | 719 | <h4 id="Section"> Section </h4> 720 | 721 | `Section` is used to create the **header/footer** view content, which is generally used in conjunction with the `List` component. 722 | 723 | Example: 724 | 725 | ```swift 726 | 727 | Section(header: Text("I'm header"), footer: Text("I'm footer")) { 728 | ForEach(0..<3) { 729 | Text("Hello \($0)") 730 | } 731 | } 732 | 733 | ``` 734 | 735 | <details close> 736 | <summary>View running results</summary> 737 | <img width="80%" src="images/example/Section.png"/> 738 | </details> 739 | 740 | <h4 id="Form"> Form </h4> 741 | 742 | `Form` A container for grouping controls used for data entry, such as in settings or inspectors. 743 | 744 | Example: 745 | 746 | ```swift 747 | 748 | Form { 749 | TextField("First Name", text: $firstName) 750 | TextField("Last Name", text: $lastName) 751 | } 752 | ``` 753 | 754 | <details close> 755 | <summary>View running results</summary> 756 | <img width="80%" src="images/example/Form.png"/> 757 | </details> 758 | 759 | [🔝](#Layout_D) 760 | 761 | <h4 id="NavigationView"> NavigationView </h4> 762 | 763 | `NavigationView` is used to create a view container that contains the top navigation bar. 764 | 765 | Example: 766 | 767 | ```swift 768 | 769 | NavigationView { 770 | Text("🧚♂️🧚♀️🧜♂️🧜♀️🧞♂️🧞♀️").blur(radius: 5) 771 | Text("Swifter Swifter") 772 | .bold() 773 | .foregroundColor(.orange) 774 | .font(.largeTitle) 775 | } 776 | .navigationBarTitle(Text("NavigationView")) 777 | ``` 778 | 779 | <details close> 780 | <summary>View running results</summary> 781 | <img width="80%" src="images/example/NavigationView.png"/> 782 | </details> 783 | 784 | [🔝](#Layout_D) 785 | 786 | <h4 id="TabView"> TabView </h4> 787 | 788 | `TabView` is used to create a view container that contains the bottom ** TabBar**. 789 | 790 | Example: 791 | 792 | ```swift 793 | 794 | TabView(selection: $index) { 795 | ForEach(0..<imgs.count) { item in 796 | TabItemPage(index: item) 797 | .tabItem{ 798 | Image(self.imgs[item]) 799 | Text("\(item)") 800 | } 801 | .tag(item) 802 | } 803 | } 804 | ``` 805 | 806 | <details close> 807 | <summary>View running results</summary> 808 | <img width="80%" src="images/example/TabView.png"/> 809 | </details> 810 | 811 | [🔝](#Layout_D) 812 | 813 | <h4 id="HSplitView"> HSplitView </h4> 814 | 815 | Waiting for release. 816 | 817 | <h4 id="VSplitView"> VSplitView </h4> 818 | 819 | Waiting for release. 820 | 821 | [🔝](#Layout_D) 822 | 823 | <h4 id="Alert"> Alert </h4> 824 | 825 | `Alert` is used to display a bullet reminder that needs to be associated with a trigger event. 826 | 827 | Example: 828 | 829 | ```swift 830 | 831 | alert(isPresented: $showAlert, content: { 832 | Alert(title: Text("确定要支付这100000000美元吗?"), 833 | message: Text("请谨慎操作\n一旦确认,钱款将立即转入对方账户"), 834 | primaryButton: .destructive(Text("确认")) { print("转出中...") }, 835 | secondaryButton: .cancel()) 836 | }).navigationBarTitle(Text("Alert")) 837 | ``` 838 | 839 | <details close> 840 | <summary>View running results</summary> 841 | <img width="80%" src="images/example/AlertPage.jpg"/> 842 | </details> 843 | 844 | [🔝](#Alert_D) 845 | 846 | 847 | <h4 id="ActionSheet"> ActionSheet </h4> 848 | 849 | `ActionSheet` is used to pop up a selection box. 850 | 851 | Example: 852 | 853 | ```swift 854 | 855 | ActionSheet(title: Text("Title"), 856 | message: Text("Message"), 857 | buttons: 858 | [.default(Text("Default"), onTrigger: { 859 | print("Default") 860 | self.showSheet = false 861 | }),.destructive(Text("destructive"), onTrigger: { 862 | print("destructive") 863 | self.showSheet = false 864 | }),.cancel({ 865 | print("Cancel") 866 | self.showSheet = false 867 | })]) 868 | ``` 869 | 870 | usage: 871 | 872 | ```swift 873 | 874 | .actionSheet(isPresented: $showSheet, content: {sheet}) 875 | 876 | ``` 877 | <details close> 878 | <summary>View running results</summary> 879 | <img width="80%" src="images/example/ActionSheet.png"/> 880 | </details> 881 | 882 | [🔝](#Alert_D) 883 | 884 | 885 | <h4 id="Modal"> Modal </h4> 886 | 887 | `Modal` is used to pop up a view. 888 | 889 | Example: 890 | 891 | ```swift 892 | 893 | Modal(Text("Modal View"),onDismiss: { 894 | print("View Dismiss !") 895 | }) 896 | 897 | ``` 898 | 899 | <details close> 900 | <summary>View running results</summary> 901 | <img width="80%" src="images/example/Modal.png"/> 902 | </details> 903 | 904 | [🔝](#Alert_D) 905 | 906 | 907 | <h4 id="Popover"> Popover </h4> 908 | 909 | `Popover` is used to pop up a view, see the results below. 910 | 911 | Example: 912 | 913 | ```swift 914 | 915 | .popover(isPresented: $showPop, content: { 916 | ImagePage() 917 | }) 918 | 919 | ``` 920 | 921 | <details close> 922 | <summary>View running results</summary> 923 | <img width="80%" src="images/example/Popover.png"/> 924 | </details> 925 | 926 | [🔝](#Alert_D) 927 | 928 | ## 📎 About 929 | 930 | * The code involved in the above example is in this repository code. It is recommended to download and run the view. 931 | * If you have better usage and suggestions about SwiftUI, look forward to sharing it! 932 | * If there are omissions and errors in the examples in this article, please create a [**Issue**](https://github.com/Jinxiansen/SwiftUI/issues/new) ! 933 | 934 | 935 | 936 | ## ✉️ Contacts 937 | 938 | email : hi@jinxiansen.com 939 | 940 | 微博 : [@晋先森](http://weibo.com/3205872327) 941 | 942 | ## 📄 License 943 | 944 | SwiftUI is released under the [MIT license](LICENSE). See LICENSE for details. 945 | 946 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | <img src="images/icon/banner.png"/> 2 | 3 | [](https://github.com/Jinxiansen/SwiftUI) 4 | [](https://swift.org) 5 | [](https://developer.apple.com/xcode) 6 | [](https://developer.apple.com/macOS) 7 | [](https://opensource.org/licenses/MIT) 8 | 9 | 本文参考 SwiftUI [官方示例](https://github.com/Jinxiansen/SwiftUI/tree/doc) 并将探索结果记录于此,希望能够对你有所帮助。 10 | 11 | 对于本文所述内容,默认你已有一定的基于 Swift 语言的开发经验,故不会详细的叙述每个细节;如果对 Swift 语法有疑问,可先学习 [Swift](https://swift.org) 语法。 12 | 13 | 14 | 有关 `SwiftUI` 的疑问,可加入 SwiftUI QQ 交流群:**18552966** ,共同探讨。 15 | 16 | [English 📔](README.md) 17 | 18 | <a href="https://github.com/Jinxiansen/Windows11/"><img src="https://github.com/Jinxiansen/SwiftUI/blob/master/images/ad/cn.png"/></a> 19 | 20 | 21 | ### [Whats New in SwiftUI?](https://developer.apple.com/xcode/swiftui/) 22 | 23 | 24 | ## 截图 25 | |View|Layout| 26 | |:---:|:---:| 27 | |<img src="images/screenshot/x1.jpg" height="50%"/>|<img src="images/screenshot/x2.jpg" height="50%"/>| 28 | 29 | ## 💻 所需环境 30 | 31 | - macOS 10.15 32 | - Xcode 11.0 33 | - iOS 13.0 34 | 35 | 36 | ## 📂 目录: 37 | 38 | ### 基础控件 39 | 40 | * <span id="Text_D">Text 文本</span> 41 | - [Text](#Text) 42 | - [TextField](#TextField) 43 | - [SecureField](#SecureField) 44 | 45 | * <span id="Image_D">Image 图片</span> 46 | - [Image](#Image) 47 | - [WebImage](#WebImage) 48 | 49 | * <span id="Button_D">Button 按钮</span> 50 | - [Button](#Button) 51 | - [PullDownButton](#PullDownButton) 52 | - [ItemBasedPopUpButton](#ItemBasedPopUpButton) 53 | - [NavigationButton](#NavigationButton) 54 | - [PresentationButton](#PresentationButton) 55 | - [EditButton](#EditButton) 56 | - [PasteButton](#PasteButton) 57 | 58 | * <span id="Picker_D">Picker 选择器</span> 59 | - [Picker](#Picker) 60 | - [DatePicker](#DatePicker) 61 | - [Toggle](#Toggle) 62 | - [Slider](#Slider) 63 | - [Stepper](#Stepper) 64 | - [SegmentedControl](#SegmentedControl) 65 | 66 | * <span id="Special_D">特殊视图</span> 67 | - [WebView](#WebView) 68 | - [UIViewController](#UIViewController) 69 | 70 | ### <span id="Layout_D">布局</span> 71 | 72 | * <span id="Stacks_D">Stacks</span> 73 | - [HStack](#HStack) 74 | - [VStack](#VStack) 75 | - [ZStack](#ZStack) 76 | 77 | * <span id="List_D">List 列表</span> 78 | - [List](#List) 79 | - [ScrollView](#ScrollView) 80 | - [ForEach](#ForEach) 81 | 82 | * <span id="Container_D">Container Views 容器视图</span> 83 | - [Group](#Group) 84 | - [GroupBox](#GroupBox) 85 | - [Section](#Section) 86 | - [Form](#Form) 87 | 88 | * <span id="Architectural_D">Architectural Views 导航、切换、排列</span> 89 | - [NavigationView](#NavigationView) 90 | - [TabView](#TabView) 91 | - [HSplitView](#HSplitView) 92 | - [VSplitView](#VSplitView) 93 | 94 | * <span id="Alert_D">Alert 弹框、选择</span> 95 | - [Alert](#Alert) 96 | - [Modal](#Modal) 97 | - [Popover](#Popover) 98 | - [Sheet](#Sheet) 99 | - [ActionSheet](#ActionSheet) 100 | 101 | 102 | ### <span id="State_D">State and Data Flow 状态和数据流</span> 103 | 104 | * <span id="Bindings_D"> Bindings </span> 105 | * [Binding](#Binding) 106 | 107 | * <span id="Data_D"> Data-Dependent Views </span> 108 | * [State](#State) 109 | * [ObjectBinding](#ObjectBinding) 110 | * [EnvironmentObject](#EnvironmentObject) 111 | 112 | * <span id="Environment_D"> Environment Values </span> 113 | * [Environment](#Environment) 114 | * [EnvironmentValues](#EnvironmentValues) 115 | 116 | * <span id="ENavigation_D"> ENavigation Models </span> 117 | * [DynamicNavigationDestinationLink](#DynamicNavigationDestinationLink) 118 | 119 | * <span id="Preferences_D"> Preferences </span> 120 | * [LocalizedStringKey](#LocalizedStringKey) 121 | 122 | * <span id="Transactions_D"> Transactions </span> 123 | * [Transaction](#Transaction) 124 | 125 | 126 | ### 手势 127 | 128 | * Basic Gestures 基本手势 129 | * [TapGesture](#TapGesture) 130 | * [LongPressGesture](#LongPressGesture) 131 | * [DragGesture](#DragGesture) 132 | * [MagnificationGesture](#MagnificationGesture) 133 | * [RotationGesture](#RotationGesture) 134 | 135 | * Combined Gestures 合并手势 136 | * [SequenceGesture](#SequenceGesture) 137 | * [SimultaneousGesture](#SimultaneousGesture) 138 | * [ExclusiveGesture](#ExclusiveGesture) 139 | 140 | * Custom Gestures 自定义手势 141 | * [AnyGesture](#AnyGesture) 142 | 143 | 144 | 145 | <h2 id="基础控件">基础控件</h2> 146 | 147 | <h4 id="Text">Text</h4> 148 | 149 | `Text` 用来展示一行或多行的文本内容,效果等同于 `UILabel`,但更加优秀。 150 | 如果要创建 `Text`, 只需通过 `Text("SwiftUI")` 即可创建; 151 | 采用链式语法,也可以为文本添加多项属性,如字体、颜色、阴影、上左下右的间距等。 152 | 153 | 示例: 154 | 155 | ```swift 156 | Text("SwiftUI") 157 | .foregroundColor(.orange) 158 | .bold() 159 | .font(.system(.largeTitle)) 160 | .fontWeight(.medium) 161 | .italic() 162 | .shadow(color: .black, radius: 1, x: 0, y: 2) 163 | ``` 164 | 165 | <details close> 166 | <summary>查看运行效果</summary> 167 | <img width="80%" src="images/example/Text.png"/> 168 | </details> 169 | 170 | > HStack 和 VStack 控件用于承载多个视图,在后面会提到。 171 | 172 | [🔝](#Text_D) 173 | 174 | <h4 id="TextField"> TextField </h4> 175 | 176 | `TextField` 用来添加普通的输入框,一般常用作文本输入。 177 | 178 | 示例: 179 | 180 | ```swift 181 | 182 | TextField(self.$name, placeholder: self.nameText, onEditingChanged: { changed in 183 | print("onEditing: \(changed)") 184 | }) { 185 | print("userName: \(self.name)") 186 | self.endEditing(true) 187 | }} 188 | .padding(10) 189 | .frame(height: 50) 190 | .textFieldStyle(RoundedBorderTextFieldStyle()) 191 | .padding(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) 192 | ``` 193 | 194 | <details close> 195 | <summary>查看运行效果</summary> 196 | <img width="80%" src="images/example/Field.png"/> 197 | </details> 198 | 199 | [🔝](#Text_D) 200 | 201 | <h4 id="SecureField"> SecureField </h4> 202 | 203 | `SecureField ` 一般作为密码输入时使用,使用方式与 `TextField` 并无差别,示例与运行效果同上 `TextField`。 204 | 205 | 206 | <h4 id="Image"> Image </h4> 207 | 208 | `Image` 控件用于展示图片。 209 | 210 | 示例: 211 | 212 | ```swift 213 | Image("icon") 214 | .resizable() 215 | .frame(width: 100, 216 | height: 100, 217 | alignment: .center) 218 | ``` 219 | 220 | <details close> 221 | <summary>查看运行效果</summary> 222 | <img width="80%" src="images/example/Image.png"/> 223 | </details> 224 | 225 | [🔝](#Text_D) 226 | 227 | <h4 id="WebImage"> WebImage </h4> 228 | 229 | `webImage` 用于下载网络图片,使用的 `URLSession`下载成功后替换原有 `Image`;你也可以在 `downloadWebImage ` 方法中使用 [Kingfisher](https://github.com/onevcat/Kingfisher) 。 230 | 231 | 示例: 232 | 233 | ```swift 234 | var body: some View { 235 | Image(uiImage: self.uiImage ?? placeholderImage) 236 | .resizable() 237 | .onAppear(perform: downloadWebImage) 238 | .frame(width: 80, 239 | height: 80, 240 | alignment: .center) 241 | .onTapGesture { 242 | print("Tap ") 243 | } 244 | } 245 | ``` 246 | 247 | <details close> 248 | <summary>查看运行效果</summary> 249 | <img width="80%" src="images/example/WebImage.png"/> 250 | </details> 251 | 252 | [🔝](#Text_D) 253 | 254 | <h4 id="Button"> Button </h4> 255 | 256 | `Button` 用于响应点击事件。 257 | 258 | 示例: 259 | 260 | ```swift 261 | Button(action: { 262 | print("Tap") 263 | }) { 264 | Text("I'm a Button") 265 | } 266 | ``` 267 | 268 | <h4 id="PullDownButton"> PullDownButton </h4> 269 | 270 | 尚未发布 271 | 272 | <h4 id="ItemBasedPopUpButton"> ItemBasedPopUpButton </h4> 273 | 274 | 尚未发布 275 | 276 | 277 | <h4 id="NavigationButton"> NavigationButton 已弃用</h4> 278 | 279 | `NavigationButtonPage ` 用以 Push 到下一个导航页面。 280 | 281 | 示例: 282 | 283 | ```swift 284 | NavigationLink(destination: NavigationButtonPage()) { 285 | Text("NavigationButton").bold() 286 | .foregroundColor(.orange) 287 | .font(.largeTitle) 288 | } 289 | .navigationBarTitle(Text("Page")) 290 | ``` 291 | 292 | <details close> 293 | <summary>查看运行效果</summary> 294 | <img width="80%" src="images/example/NavigationButton.png"/> 295 | </details> 296 | 297 | [🔝](#Button_D) 298 | 299 | <h4 id="PresentationButton" style='color:red'> PresentationButton </h4> 300 | 301 | `PresentationButton` ~~用以弹出一个页面。~~ 已经弃用了,请使用 `NavigationLink` 302 | 303 | 304 | [🔝](#Button_D) 305 | 306 | <h4 id="EditButton"> EditButton </h4> 307 | 308 | `EditButton` 用以触发编辑状态,使用时只需在 `navigationBarItems ` 设置即可。 309 | 310 | 示例: 311 | 312 | ```swift 313 | navigationBarItems(trailing: EditButton()) 314 | ``` 315 | 316 | <details close> 317 | <summary>查看运行效果</summary> 318 | <img width="80%" src="images/example/EditButton.png"/> 319 | </details> 320 | 321 | [🔝](#Button_D) 322 | 323 | <h4 id="PasteButton"> PasteButton </h4> 324 | 325 | 尚未发布 326 | 327 | 328 | <h4 id="Picker"> Picker </h4> 329 | 330 | `Picker` 可自定义数据源的选择器。 331 | 332 | 示例: 333 | 334 | ```swift 335 | Picker(selection: $leftIndex, label: Text("Picker")) { 336 | ForEach(0..<leftSource.count) { 337 | Text(self.leftSource[$0]).tag($0) 338 | } 339 | }.frame(width: UIScreen.main.bounds.width/2) 340 | ``` 341 | 342 | <details close> 343 | <summary>查看运行效果</summary> 344 | <img width="80%" src="images/example/Picker.png"/> 345 | </details> 346 | 347 | [🔝](#Picker_D) 348 | 349 | <h4 id="DatePicker"> DatePicker </h4> 350 | 351 | `DatePicker` 用于选择绝对日期的控件。 352 | 353 | 示例: 354 | 355 | ```swift 356 | DatePicker(selection: $server.date, 357 | in: server.spaceDate, 358 | displayedComponents: .date, label: { 359 | Text("") 360 | }) 361 | ``` 362 | 363 | <details close> 364 | <summary>查看运行效果</summary> 365 | <img width="80%" src="images/example/DatePicker.png"/> 366 | </details> 367 | 368 | [🔝](#Picker_D) 369 | 370 | <h4 id="Toggle"> Toggle </h4> 371 | 372 | `Toggle` 用于切换选中状态。 373 | 374 | 示例: 375 | 376 | ```swift 377 | Toggle(isOn: $isOn) { 378 | Text("State: \(self.isOn == true ? "开":"关")") 379 | }.padding(20) 380 | ``` 381 | 382 | <details close> 383 | <summary>查看运行效果</summary> 384 | <img width="80%" src="images/example/Toggle.png"/> 385 | </details> 386 | 387 | [🔝](#Picker_D) 388 | 389 | <h4 id="Slider"> Slider </h4> 390 | 391 | `Slider ` 用于从有限值范围中选值的控件。 392 | 393 | 示例: 394 | 395 | ```swift 396 | Slider(value: $data.rating) 397 | ``` 398 | 399 | <details close> 400 | <summary>查看运行效果</summary> 401 | <img width="80%" src="images/example/Slider.png"/> 402 | </details> 403 | 404 | [🔝](#Picker_D) 405 | 406 | <h4 id="Stepper"> Stepper </h4> 407 | 408 | `Stepper ` 用以增加或减少数值。 409 | 410 | 示例: 411 | 412 | ```swift 413 | Stepper(value: $value, step: 2, onEditingChanged: { c in 414 | print(c) 415 | }) { 416 | Text("Stepper Value: \(self.value)") 417 | }.padding(50) 418 | ``` 419 | 420 | <details close> 421 | <summary>查看运行效果</summary> 422 | <img width="80%" src="images/example/Stepper.png"/> 423 | </details> 424 | 425 | [🔝](#Picker_D) 426 | 427 | <h4 id="SegmentedControl" style="color:red">SegmentedControl 已经弃用了</h4> 428 | 429 | 430 | ~~`SegmentedControl` 用以分段条件选择。~~ 431 | 432 | 示例: 433 | 434 | ```swift 435 | SegmentedControl(selection: $currentIndex) { 436 | ForEach(0..<items.count) { index in 437 | Text(self.items[index]).tag(index) 438 | } 439 | }.tapAction { 440 | print("currentIndex: \(self.currentIndex)") 441 | } 442 | ``` 443 | 444 | <details close> 445 | <summary>查看完整示例及运行效果</summary> 446 | <img width="80%" src="images/example/SegmentedControl.png"/> 447 | </details> 448 | 449 | [🔝](#Picker_D) 450 | 451 | 452 | <h4 id="WebView"> WebView </h4> 453 | 454 | `WebView` 用于展示一个打开的网页。 455 | 456 | 示例: 457 | 458 | ```swift 459 | struct WebViewPage : UIViewRepresentable { 460 | func makeUIView(context: Context) -> WKWebView { 461 | return WKWebView() 462 | } 463 | func updateUIView(_ uiView: WKWebView, context: Context) { 464 | let req = URLRequest(url: URL(string: "https://www.apple.com")!) 465 | uiView.load(req) 466 | } 467 | } 468 | ``` 469 | 470 | <details close> 471 | <summary>查看运行效果</summary> 472 | <img width="80%" src="images/example/WebView.png"/> 473 | </details> 474 | 475 | [🔝](#Special_D) 476 | 477 | 478 | <h4 id="UIViewController"> UIViewController </h4> 479 | 480 | `UIViewController ` 用于展示在 **SwiftUI** 中打开 **UIKit** 的 **UIViewController** ,并且在 **UIViewController** 中打开 `SwiftUI` View。 481 | 482 | 示例: 483 | 484 | 先定义: 485 | 486 | ```swift 487 | struct ControllerPage<T: UIViewController> : UIViewControllerRepresentable { 488 | 489 | typealias UIViewControllerType = UIViewController 490 | 491 | func makeUIViewController(context: UIViewControllerRepresentableContext<ControllerPage>) -> UIViewController { 492 | return T() 493 | } 494 | 495 | func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ControllerPage>) { 496 | debugPrint("\(#function):\(type(of: T.self))") 497 | } 498 | 499 | } 500 | ``` 501 | 502 | 然后调用: 503 | 504 | ```swift 505 | NavigationButton(destination: ControllerPage<UIKitController>()) { 506 | PageRow(title: "UIViewController",subTitle: "打开 UIViewController") 507 | 508 | } 509 | ``` 510 | 511 | <details close> 512 | <summary>查看运行效果</summary> 513 | <img width="80%" src="images/example/UIViewController.png"/> 514 | <img width="80%" src="images/example/UIViewController2.png"/> 515 | </details> 516 | 517 | [🔝](#Special_D) 518 | 519 | ### 布局 520 | 521 | <h4 id="HStack"> HStack </h4> 522 | 523 | `HStack` 用于将子视图排列在水平线上的视图。 524 | 525 | 示例: 526 | 527 | ```swift 528 | HStack { 529 | Text("made in China.") 530 | Divider() // Just add a line. 531 | Text("the People's Republic Of China.") 532 | } 533 | ``` 534 | 535 | <details close> 536 | <summary>查看运行效果</summary> 537 | <img width="80%" src="images/example/HStack.png"/> 538 | </details> 539 | 540 | [🔝](#Layout_D) 541 | 542 | <h4 id="VStack"> VStack </h4> 543 | 544 | `VStack` 用于将子视图排列在垂直线上的视图。 545 | 546 | 示例: 547 | 548 | ```swift 549 | VStack { 550 | Text("made in China.") 551 | Divider() // Just add a line. 552 | Text("the People's Republic Of China.") 553 | } 554 | ``` 555 | 556 | <details close> 557 | <summary>查看运行效果</summary> 558 | <img width="80%" src="images/example/VStack.png"/> 559 | </details> 560 | 561 | [🔝](#Layout_D) 562 | 563 | <h4 id="ZStack"> ZStack </h4> 564 | 565 | `ZStack` 用于覆盖子视图,在两轴上对齐。 566 | 567 | 示例: 568 | 569 | ```swift 570 | ZStack { 571 | Text("made in China.") 572 | Divider() // Just add a line. 573 | Text("the People's Republic Of China.") 574 | } 575 | ``` 576 | 577 | <details close> 578 | <summary>查看运行效果</summary> 579 | <img width="80%" src="images/example/ZStack.png"/> 580 | </details> 581 | 582 | [🔝](#Layout_D) 583 | 584 | <h4 id="List"> List </h4> 585 | 586 | `List` 列表容器,用以显示一列数据。 587 | 588 | 示例: 589 | 590 | ```swift 591 | List(0..<5) { item in 592 | Text("Hello World !") 593 | }.navigationBarTitle(Text("List"), displayMode: .large) 594 | ``` 595 | 596 | <details close> 597 | <summary>查看运行效果</summary> 598 | <img width="80%" src="images/example/List.png"/> 599 | </details> 600 | 601 | [🔝](#Layout_D) 602 | 603 | <h4 id="ScrollView"> ScrollView </h4> 604 | 605 | `ScrollView` 是一个滚动视图容器。 606 | 607 | 示例: 608 | 609 | ```swift 610 | ScrollView { 611 | Text("SwiftUI").padding(20) 612 | Divider() 613 | Image("icon").resizable() 614 | .frame(width: 300, height: 300, alignment: .center) 615 | Divider() 616 | Text("Views and ... user interface.") 617 | } 618 | .border(Color.gray.gradient, width: 1) 619 | .cornerRadius(10) 620 | .padding(10) 621 | .navigationBarTitle(Text("ScrollView")) 622 | ``` 623 | 624 | <details close> 625 | <summary>查看运行效果</summary> 626 | <img width="80%" src="images/example/ScrollView.png"/> 627 | </details> 628 | 629 | [🔝](#Layout_D) 630 | 631 | <h4 id="ForEach"> ForEach </h4> 632 | 633 | `ForEach` 用于根据已有数据的集合展示视图。 634 | 635 | 示例: 636 | 637 | ```swift 638 | let data = (0..<5) 639 | var body: some View { 640 | ForEach(data) { e in 641 | Text("Hello \(e)") 642 | .bold() 643 | .font(.system(size: 25, design: .monospaced)) 644 | .padding(5) 645 | } 646 | ``` 647 | 648 | <details close> 649 | <summary>查看运行效果</summary> 650 | <img width="80%" src="images/example/ForEach.png"/> 651 | </details> 652 | 653 | [🔝](#Layout_D) 654 | 655 | <h4 id="Group"> Group </h4> 656 | 657 | `Group` 用于集合多个视图,对 Group 设置的属性,将作用于每个子视图。 658 | 659 | 示例: 660 | 661 | ```swift 662 | Group { 663 | Text("Hello World !") 664 | Text("Hello World !") 665 | } 666 | ``` 667 | 668 | <details close> 669 | <summary>查看运行效果</summary> 670 | <img width="80%" src="images/example/Group.png"/> 671 | </details> 672 | 673 | [🔝](#Layout_D) 674 | 675 | <h4 id="GroupBox"> GroupBox </h4> 676 | 677 | 尚未发布 678 | 679 | 680 | <h4 id="Section"> Section </h4> 681 | 682 | `Section` 用于创建带头/尾部的视图内容,一般结合 `List` 组件使用。 683 | 684 | 示例: 685 | 686 | ```swift 687 | Section(header: Text("I'm header"), footer: Text("I'm footer")) { 688 | ForEach(0..<3) { 689 | Text("Hello \($0)") 690 | } 691 | } 692 | ``` 693 | 694 | <details close> 695 | <summary>查看运行效果</summary> 696 | <img width="80%" src="images/example/Section.png"/> 697 | </details> 698 | 699 | <h4 id="Form"> Form </h4> 700 | 701 | `Form` 是对一组数据输入进行控制的容器。 702 | 703 | Example: 704 | 705 | ```swift 706 | Form { 707 | TextField("First Name", text: $firstName) 708 | TextField("Last Name", text: $lastName) 709 | } 710 | ``` 711 | 712 | <details close> 713 | <summary>查看运行效果</summary> 714 | <img width="80%" src="images/example/Form.png"/> 715 | </details> 716 | 717 | [🔝](#Layout_D) 718 | 719 | <h4 id="NavigationView"> NavigationView </h4> 720 | 721 | `NavigationView` 用于创建包含顶部导航栏的视图容器。 722 | 723 | 示例: 724 | 725 | ```swift 726 | NavigationView { 727 | Text("🧚♂️🧚♀️🧜♂️🧜♀️🧞♂️🧞♀️").blur(radius: 5) 728 | Text("Swifter Swifter") 729 | .bold() 730 | .foregroundColor(.orange) 731 | .font(.largeTitle) 732 | } 733 | .navigationBarTitle(Text("NavigationView")) 734 | ``` 735 | 736 | <details close> 737 | <summary>查看运行效果</summary> 738 | <img width="80%" src="images/example/NavigationView.png"/> 739 | </details> 740 | 741 | [🔝](#Layout_D) 742 | 743 | <h4 id="TabView"> TabView </h4> 744 | 745 | `TabView` 用于创建包含底部 ** TabBar** 的视图容器。 746 | 747 | 示例: 748 | 749 | ```swift 750 | TabView(selection: $index) { 751 | ForEach(0..<imgs.count) { item in 752 | TabItemPage(index: item) 753 | .tabItem{ 754 | Image(self.imgs[item]) 755 | Text("\(item)") 756 | } 757 | .tag(item) 758 | } 759 | } 760 | ``` 761 | 762 | <details close> 763 | <summary>查看运行效果</summary> 764 | <img width="80%" src="images/example/TabView.png"/> 765 | </details> 766 | 767 | [🔝](#Layout_D) 768 | 769 | <h4 id="HSplitView"> HSplitView </h4> 770 | 771 | 尚未发布 772 | 773 | <h4 id="VSplitView"> VSplitView </h4> 774 | 775 | 尚未发布 776 | 777 | 778 | <h4 id="Alert"> Alert </h4> 779 | 780 | `Alert` 用于展示一个弹框提醒,需要与点击事件关联起来。 781 | 782 | 示例: 783 | 784 | ```swift 785 | alert(isPresented: $showAlert, content: { 786 | Alert(title: Text("确定要支付这100000000美元吗?"), 787 | message: Text("请谨慎操作\n一旦确认,钱款将立即转入对方账户"), 788 | primaryButton: .destructive(Text("确认")) { print("转出中...") }, 789 | secondaryButton: .cancel()) 790 | }).navigationBarTitle(Text("Alert")) 791 | ``` 792 | 793 | <details close> 794 | <summary>查看运行效果</summary> 795 | <img width="80%" src="images/example/AlertPage.jpg"/> 796 | </details> 797 | 798 | [🔝](#Alert_D) 799 | 800 | 801 | <h4 id="ActionSheet"> ActionSheet </h4> 802 | 803 | `ActionSheet` 用于弹出一个选择框。 804 | 805 | 示例: 806 | 807 | ```swift 808 | ActionSheet(title: Text("Title"), 809 | message: Text("Message"), 810 | buttons: 811 | [.default(Text("Default"), onTrigger: { 812 | print("Default") 813 | self.showSheet = false 814 | }),.destructive(Text("destructive"), onTrigger: { 815 | print("destructive") 816 | self.showSheet = false 817 | }),.cancel({ 818 | print("Cancel") 819 | self.showSheet = false 820 | })]) 821 | ``` 822 | 823 | 使用: 824 | ```swift 825 | .actionSheet(isPresented: $showSheet, content: {sheet}) 826 | ``` 827 | 828 | <details close> 829 | <summary>查看运行效果</summary> 830 | <img width="80%" src="images/example/ActionSheet.png"/> 831 | </details> 832 | 833 | [🔝](#Alert_D) 834 | 835 | 836 | <h4 id="Modal"> Modal </h4> 837 | 838 | `Modal` 用于弹出一个视图。 839 | 840 | 示例: 841 | 842 | ```swift 843 | Modal(Text("Modal View"),onDismiss: { 844 | print("View Dismiss !") 845 | }) 846 | ``` 847 | 848 | <details close> 849 | <summary>查看运行效果</summary> 850 | <img width="80%" src="images/example/Modal.png"/> 851 | </details> 852 | 853 | [🔝](#Alert_D) 854 | 855 | 856 | <h4 id="Popover"> Popover </h4> 857 | 858 | `Popover` 用于弹出一个视图,样式见下方运行结果。 859 | 860 | 示例: 861 | 862 | ```swift 863 | .popover(isPresented: $showPop, content: { 864 | ImagePage() 865 | }) 866 | ``` 867 | 868 | <details close> 869 | <summary>查看运行效果</summary> 870 | <img width="80%" src="images/example/Popover.png"/> 871 | </details> 872 | 873 | [🔝](#Alert_D) 874 | 875 | 876 | ## 📎 About 877 | 878 | * 以上示例中所涉及代码,皆在本仓库代码中,建议下载并运行查看。 879 | * 如果有关于 SwiftUI 更好的用法与建议,期待能够一起分享! 880 | * 如果本文示例内容有疏漏和错误之处,欢迎提 [**Issue**](https://github.com/Jinxiansen/SwiftUI/issues/new) ! 881 | 882 | 883 | 884 | ## ✉️ Contacts 885 | 886 | email : hi@jinxiansen.com 887 | 888 | 微博 : [@晋先森](http://weibo.com/3205872327) 889 | 890 | 891 | ## 📄 License 892 | 893 | 894 | SwiftUI is released under the [MIT license](LICENSE). See LICENSE for details. 895 | 896 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: pmarsceill/just-the-docs 2 | -------------------------------------------------------------------------------- /images/ad/cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/ad/cn.png -------------------------------------------------------------------------------- /images/ad/en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/ad/en.png -------------------------------------------------------------------------------- /images/example/ActionSheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/ActionSheet.png -------------------------------------------------------------------------------- /images/example/Alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Alert.png -------------------------------------------------------------------------------- /images/example/AlertPage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/AlertPage.jpg -------------------------------------------------------------------------------- /images/example/Button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Button.png -------------------------------------------------------------------------------- /images/example/DatePicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/DatePicker.png -------------------------------------------------------------------------------- /images/example/EditButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/EditButton.png -------------------------------------------------------------------------------- /images/example/Field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Field.png -------------------------------------------------------------------------------- /images/example/ForEach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/ForEach.png -------------------------------------------------------------------------------- /images/example/Form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Form.png -------------------------------------------------------------------------------- /images/example/Group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Group.png -------------------------------------------------------------------------------- /images/example/HStack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/HStack.png -------------------------------------------------------------------------------- /images/example/Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Image.png -------------------------------------------------------------------------------- /images/example/List.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/List.png -------------------------------------------------------------------------------- /images/example/Modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Modal.png -------------------------------------------------------------------------------- /images/example/NavigationButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/NavigationButton.png -------------------------------------------------------------------------------- /images/example/NavigationView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/NavigationView.png -------------------------------------------------------------------------------- /images/example/Picker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Picker.png -------------------------------------------------------------------------------- /images/example/Popover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Popover.png -------------------------------------------------------------------------------- /images/example/PresentationButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/PresentationButton.png -------------------------------------------------------------------------------- /images/example/ScrollView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/ScrollView.png -------------------------------------------------------------------------------- /images/example/Section.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Section.png -------------------------------------------------------------------------------- /images/example/SegmentedControl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/SegmentedControl.png -------------------------------------------------------------------------------- /images/example/Slider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Slider.png -------------------------------------------------------------------------------- /images/example/Stepper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Stepper.png -------------------------------------------------------------------------------- /images/example/TabView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/TabView.png -------------------------------------------------------------------------------- /images/example/Text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Text.png -------------------------------------------------------------------------------- /images/example/Toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/Toggle.png -------------------------------------------------------------------------------- /images/example/UIViewController.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/UIViewController.png -------------------------------------------------------------------------------- /images/example/UIViewController2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/UIViewController2.png -------------------------------------------------------------------------------- /images/example/VStack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/VStack.png -------------------------------------------------------------------------------- /images/example/WebImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/WebImage.png -------------------------------------------------------------------------------- /images/example/WebView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/WebView.png -------------------------------------------------------------------------------- /images/example/ZStack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/example/ZStack.png -------------------------------------------------------------------------------- /images/icon/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/icon/banner.png -------------------------------------------------------------------------------- /images/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/icon/icon.png -------------------------------------------------------------------------------- /images/icon/icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/icon/icon2.png -------------------------------------------------------------------------------- /images/icon/swiftUI.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/icon/swiftUI.sketch -------------------------------------------------------------------------------- /images/icon/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/icon/top.png -------------------------------------------------------------------------------- /images/screenshot/x1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/screenshot/x1.jpg -------------------------------------------------------------------------------- /images/screenshot/x2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/screenshot/x2.jpg -------------------------------------------------------------------------------- /images/windows11/launchpad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jinxiansen/SwiftUI/d8192c12098f80f8a4bd2387a969f010c38c5773/images/windows11/launchpad.png --------------------------------------------------------------------------------