├── .gitignore
├── README.md
├── StudyGroupEventFetcherForSwiftUI.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcuserdata
│ └── milanista.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── StudyGroupEventFetcherForSwiftUI
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── app_icon1024.png
│ │ ├── app_icon120-1.png
│ │ ├── app_icon120.png
│ │ ├── app_icon152.png
│ │ ├── app_icon167.png
│ │ ├── app_icon180.png
│ │ ├── app_icon20.png
│ │ ├── app_icon29.png
│ │ ├── app_icon40-1.png
│ │ ├── app_icon40-2.png
│ │ ├── app_icon40.png
│ │ ├── app_icon58-1.png
│ │ ├── app_icon58.png
│ │ ├── app_icon60.png
│ │ ├── app_icon76.png
│ │ ├── app_icon80-1.png
│ │ ├── app_icon80.png
│ │ └── app_icon87.png
│ ├── Contents.json
│ └── Detail
│ │ ├── Contents.json
│ │ └── img_yumemi_swift.imageset
│ │ ├── Contents.json
│ │ └── img_yumemi_swift.png
├── Base.lproj
│ └── LaunchScreen.storyboard
├── Info.plist
├── Model
│ ├── Event.swift
│ ├── PinItem.swift
│ └── StudyGroup.swift
├── Other
│ ├── APIError.swift
│ ├── StudyGroupDateFormatter.swift
│ └── StudyGroupEventFetcher.swift
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── StudyGroupEventFetcherForSwiftUIApp.swift
├── ViewModel
│ └── TopListViewModel.swift
└── Views
│ ├── Common
│ ├── LoadingView.swift
│ └── LoadingViewModifier.swift
│ ├── EventDetail
│ ├── EventDetailButtonView.swift
│ ├── EventDetailMapButtonView.swift
│ ├── EventDetailPartView.swift
│ └── EventDetailView.swift
│ ├── Map
│ └── NewMapView.swift
│ ├── Safari
│ └── SafariView.swift
│ └── TopEventList
│ ├── EventLabelView.swift
│ ├── EventRowView.swift
│ └── TopListView.swift
├── StudyGroupEventFetcherForSwiftUITests
├── Info.plist
└── StudyGroupEventFetcherForSwiftUITests.swift
└── StudyGroupEventFetcherForSwiftUIUITests
├── Info.plist
└── StudyGroupEventFetcherForSwiftUIUITests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | project.xcworkspace/
2 | xcuserdata/
3 | build/
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # StudyGroupEventFetcherForSwiftUI
2 |
3 | This is a sample project of SwiftUI that displays the data obtained via external API in "List".
4 | This App fetches study group event list via connpass API.
5 | For example, YUMEMI.swift. We hold on a regular basis.
6 |
7 | ## Qiita
8 |
9 | Wrote article.
10 |
11 | [https://qiita.com/MilanistaDev/items/64dca8c9d5099a19529e](https://qiita.com/MilanistaDev/items/64dca8c9d5099a19529e)
12 |
13 | ### iOS 16 Support
14 |
15 | [https://qiita.com/MilanistaDev/items/fce3987b02a284f5112a](https://qiita.com/MilanistaDev/items/fce3987b02a284f5112a)
16 |
17 | ## Enjoy SwiftUI vol2
18 |
19 | This sample is for live coding of Enjoy SwiftUI vol2.
20 | The event link is as bellow.
21 |
22 | https://yumemi.connpass.com/event/151594/
23 |
24 | ## connpass Event Search API
25 |
26 | **Request URL**
27 | `https://connpass.com/api/v1/event/`
28 |
29 | This sample code's Link is follow.
30 | `https://connpass.com/api/v1/event/?keyword=YUMEMI.swift`
31 |
32 | If you'd like to browse the detail of this API, please access this link.
33 | [https://connpass.com/about/api/](https://connpass.com/about/api/)
34 |
35 | ## Run this code
36 | 
37 |
38 |
39 | ## Support
40 | * macOS Catalina 10.15.1 and later
41 | * Xcode 11.2.1 and later
42 |
43 | ## App update history
44 |
45 | |App Version|Date|MEMO|
46 | |:--:|:--:|:--|
47 | |1.0|2019-11-08|v1.0 released.|
48 | |1.0.1|2019-12-23|Implemented DetailView Screen.|
49 | |1.0.2|2020-04-14|Fixed a bug that the list is not displayed
when there is no location information of the event.|
50 | |1.0.3|2020-06-24|Add zoom-in and out buttons on the MapVew. Fixed a bug. Some refactorings.|
51 |
52 | ## Contact
53 |
54 | Please feel free to contact us if you find a bug or have any feedback.
55 | Suggestions for adding functions and code corrections are also welcome.
56 |
57 | ```swift
58 | let name = "Takuya Aso"
59 | let email = "milanista224" + "@" + "icloud.com"
60 | let profession = "iOS Engineer"
61 | let location = "Tokyo"
62 | ```
63 |
64 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | FD0506D1236C46A4003260B9 /* StudyGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0506D0236C46A4003260B9 /* StudyGroup.swift */; };
11 | FD0506D3236C471E003260B9 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0506D2236C471E003260B9 /* Event.swift */; };
12 | FD0506D6236C4A8F003260B9 /* TopListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0506D5236C4A8F003260B9 /* TopListView.swift */; };
13 | FD0506D8236C4FA5003260B9 /* EventRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0506D7236C4FA5003260B9 /* EventRowView.swift */; };
14 | FD0506DA23712219003260B9 /* EventDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0506D923712219003260B9 /* EventDetailView.swift */; };
15 | FD0506DC2371282C003260B9 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0506DB2371282C003260B9 /* SafariView.swift */; };
16 | FD50073623AFBEEE00C369EF /* EventDetailPartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD50073523AFBEEE00C369EF /* EventDetailPartView.swift */; };
17 | FD50ECAD23717D3B00BC8342 /* TopListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD50ECAC23717D3B00BC8342 /* TopListViewModel.swift */; };
18 | FD525C65237133AE00F9C171 /* StudyGroupEventFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD525C64237133AE00F9C171 /* StudyGroupEventFetcher.swift */; };
19 | FD794B6D2462D35B00C000CD /* EventDetailMapButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD794B6C2462D35B00C000CD /* EventDetailMapButtonView.swift */; };
20 | FD9E6FD6294D61B000979FFF /* LoadingViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9E6FD5294D61B000979FFF /* LoadingViewModifier.swift */; };
21 | FD9E6FDE29504D5A00979FFF /* PinItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9E6FDD29504D5A00979FFF /* PinItem.swift */; };
22 | FD9E6FE029504FE000979FFF /* NewMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9E6FDF29504FE000979FFF /* NewMapView.swift */; };
23 | FD9E6FE42952BB3400979FFF /* APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9E6FE32952BB3400979FFF /* APIError.swift */; };
24 | FD9E6FE62953260500979FFF /* StudyGroupEventFetcherForSwiftUIApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9E6FE52953260500979FFF /* StudyGroupEventFetcherForSwiftUIApp.swift */; };
25 | FD9EB141236C33EF00DD6367 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FD9EB140236C33EF00DD6367 /* Assets.xcassets */; };
26 | FD9EB144236C33EF00DD6367 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FD9EB143236C33EF00DD6367 /* Preview Assets.xcassets */; };
27 | FD9EB147236C33EF00DD6367 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FD9EB145236C33EF00DD6367 /* LaunchScreen.storyboard */; };
28 | FD9EB152236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9EB151236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.swift */; };
29 | FD9EB15D236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9EB15C236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.swift */; };
30 | FDA2705C24A7873A009A8505 /* EventLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA2705B24A7873A009A8505 /* EventLabelView.swift */; };
31 | FDAE1B78237173C900217BD1 /* StudyGroupDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDAE1B77237173C900217BD1 /* StudyGroupDateFormatter.swift */; };
32 | FDEA054024ADE2B700AC44EC /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDEA053F24ADE2B700AC44EC /* LoadingView.swift */; };
33 | FDF7EB90244B2B3000BF1A6E /* EventDetailButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF7EB8F244B2B3000BF1A6E /* EventDetailButtonView.swift */; };
34 | /* End PBXBuildFile section */
35 |
36 | /* Begin PBXContainerItemProxy section */
37 | FD9EB14E236C33EF00DD6367 /* PBXContainerItemProxy */ = {
38 | isa = PBXContainerItemProxy;
39 | containerPortal = FD9EB12F236C33EE00DD6367 /* Project object */;
40 | proxyType = 1;
41 | remoteGlobalIDString = FD9EB136236C33EE00DD6367;
42 | remoteInfo = StudyGroupEventFetcherForSwiftUI;
43 | };
44 | FD9EB159236C33EF00DD6367 /* PBXContainerItemProxy */ = {
45 | isa = PBXContainerItemProxy;
46 | containerPortal = FD9EB12F236C33EE00DD6367 /* Project object */;
47 | proxyType = 1;
48 | remoteGlobalIDString = FD9EB136236C33EE00DD6367;
49 | remoteInfo = StudyGroupEventFetcherForSwiftUI;
50 | };
51 | /* End PBXContainerItemProxy section */
52 |
53 | /* Begin PBXFileReference section */
54 | FD0506D0236C46A4003260B9 /* StudyGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyGroup.swift; sourceTree = ""; };
55 | FD0506D2236C471E003260B9 /* Event.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = ""; };
56 | FD0506D5236C4A8F003260B9 /* TopListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopListView.swift; sourceTree = ""; };
57 | FD0506D7236C4FA5003260B9 /* EventRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventRowView.swift; sourceTree = ""; };
58 | FD0506D923712219003260B9 /* EventDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventDetailView.swift; sourceTree = ""; };
59 | FD0506DB2371282C003260B9 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = ""; };
60 | FD50073523AFBEEE00C369EF /* EventDetailPartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventDetailPartView.swift; sourceTree = ""; };
61 | FD50ECAC23717D3B00BC8342 /* TopListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopListViewModel.swift; sourceTree = ""; };
62 | FD525C64237133AE00F9C171 /* StudyGroupEventFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyGroupEventFetcher.swift; sourceTree = ""; };
63 | FD794B6C2462D35B00C000CD /* EventDetailMapButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventDetailMapButtonView.swift; sourceTree = ""; };
64 | FD9E6FD5294D61B000979FFF /* LoadingViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewModifier.swift; sourceTree = ""; };
65 | FD9E6FDD29504D5A00979FFF /* PinItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinItem.swift; sourceTree = ""; };
66 | FD9E6FDF29504FE000979FFF /* NewMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewMapView.swift; sourceTree = ""; };
67 | FD9E6FE32952BB3400979FFF /* APIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIError.swift; sourceTree = ""; };
68 | FD9E6FE52953260500979FFF /* StudyGroupEventFetcherForSwiftUIApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyGroupEventFetcherForSwiftUIApp.swift; sourceTree = ""; };
69 | FD9EB137236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StudyGroupEventFetcherForSwiftUI.app; sourceTree = BUILT_PRODUCTS_DIR; };
70 | FD9EB140236C33EF00DD6367 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
71 | FD9EB143236C33EF00DD6367 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
72 | FD9EB146236C33EF00DD6367 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
73 | FD9EB148236C33EF00DD6367 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
74 | FD9EB14D236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StudyGroupEventFetcherForSwiftUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
75 | FD9EB151236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyGroupEventFetcherForSwiftUITests.swift; sourceTree = ""; };
76 | FD9EB153236C33EF00DD6367 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
77 | FD9EB158236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StudyGroupEventFetcherForSwiftUIUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
78 | FD9EB15C236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyGroupEventFetcherForSwiftUIUITests.swift; sourceTree = ""; };
79 | FD9EB15E236C33EF00DD6367 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
80 | FDA2705B24A7873A009A8505 /* EventLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventLabelView.swift; sourceTree = ""; };
81 | FDAE1B77237173C900217BD1 /* StudyGroupDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyGroupDateFormatter.swift; sourceTree = ""; };
82 | FDEA053F24ADE2B700AC44EC /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; };
83 | FDF7EB8F244B2B3000BF1A6E /* EventDetailButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventDetailButtonView.swift; sourceTree = ""; };
84 | /* End PBXFileReference section */
85 |
86 | /* Begin PBXFrameworksBuildPhase section */
87 | FD9EB134236C33EE00DD6367 /* Frameworks */ = {
88 | isa = PBXFrameworksBuildPhase;
89 | buildActionMask = 2147483647;
90 | files = (
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | FD9EB14A236C33EF00DD6367 /* Frameworks */ = {
95 | isa = PBXFrameworksBuildPhase;
96 | buildActionMask = 2147483647;
97 | files = (
98 | );
99 | runOnlyForDeploymentPostprocessing = 0;
100 | };
101 | FD9EB155236C33EF00DD6367 /* Frameworks */ = {
102 | isa = PBXFrameworksBuildPhase;
103 | buildActionMask = 2147483647;
104 | files = (
105 | );
106 | runOnlyForDeploymentPostprocessing = 0;
107 | };
108 | /* End PBXFrameworksBuildPhase section */
109 |
110 | /* Begin PBXGroup section */
111 | FD0506CF236C4662003260B9 /* Model */ = {
112 | isa = PBXGroup;
113 | children = (
114 | FD0506D0236C46A4003260B9 /* StudyGroup.swift */,
115 | FD0506D2236C471E003260B9 /* Event.swift */,
116 | FD9E6FDD29504D5A00979FFF /* PinItem.swift */,
117 | );
118 | path = Model;
119 | sourceTree = "";
120 | };
121 | FD0506D4236C4A70003260B9 /* Views */ = {
122 | isa = PBXGroup;
123 | children = (
124 | FDEA053E24ADE2A000AC44EC /* Common */,
125 | FD50073223AFBDE700C369EF /* TopEventList */,
126 | FD50073323AFBDFC00C369EF /* EventDetail */,
127 | FD50073723AFC29000C369EF /* Map */,
128 | FD50073423AFBE1300C369EF /* Safari */,
129 | );
130 | path = Views;
131 | sourceTree = "";
132 | };
133 | FD50073223AFBDE700C369EF /* TopEventList */ = {
134 | isa = PBXGroup;
135 | children = (
136 | FD0506D5236C4A8F003260B9 /* TopListView.swift */,
137 | FD0506D7236C4FA5003260B9 /* EventRowView.swift */,
138 | FDA2705B24A7873A009A8505 /* EventLabelView.swift */,
139 | );
140 | path = TopEventList;
141 | sourceTree = "";
142 | };
143 | FD50073323AFBDFC00C369EF /* EventDetail */ = {
144 | isa = PBXGroup;
145 | children = (
146 | FD0506D923712219003260B9 /* EventDetailView.swift */,
147 | FD794B6C2462D35B00C000CD /* EventDetailMapButtonView.swift */,
148 | FD50073523AFBEEE00C369EF /* EventDetailPartView.swift */,
149 | FDF7EB8F244B2B3000BF1A6E /* EventDetailButtonView.swift */,
150 | );
151 | path = EventDetail;
152 | sourceTree = "";
153 | };
154 | FD50073423AFBE1300C369EF /* Safari */ = {
155 | isa = PBXGroup;
156 | children = (
157 | FD0506DB2371282C003260B9 /* SafariView.swift */,
158 | );
159 | path = Safari;
160 | sourceTree = "";
161 | };
162 | FD50073723AFC29000C369EF /* Map */ = {
163 | isa = PBXGroup;
164 | children = (
165 | FD9E6FDF29504FE000979FFF /* NewMapView.swift */,
166 | );
167 | path = Map;
168 | sourceTree = "";
169 | };
170 | FD50ECAB23717D1900BC8342 /* ViewModel */ = {
171 | isa = PBXGroup;
172 | children = (
173 | FD50ECAC23717D3B00BC8342 /* TopListViewModel.swift */,
174 | );
175 | path = ViewModel;
176 | sourceTree = "";
177 | };
178 | FD525C632371338100F9C171 /* Other */ = {
179 | isa = PBXGroup;
180 | children = (
181 | FD525C64237133AE00F9C171 /* StudyGroupEventFetcher.swift */,
182 | FDAE1B77237173C900217BD1 /* StudyGroupDateFormatter.swift */,
183 | FD9E6FE32952BB3400979FFF /* APIError.swift */,
184 | );
185 | path = Other;
186 | sourceTree = "";
187 | };
188 | FD9EB12E236C33EE00DD6367 = {
189 | isa = PBXGroup;
190 | children = (
191 | FD9EB139236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI */,
192 | FD9EB150236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests */,
193 | FD9EB15B236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests */,
194 | FD9EB138236C33EE00DD6367 /* Products */,
195 | );
196 | sourceTree = "";
197 | };
198 | FD9EB138236C33EE00DD6367 /* Products */ = {
199 | isa = PBXGroup;
200 | children = (
201 | FD9EB137236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI.app */,
202 | FD9EB14D236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.xctest */,
203 | FD9EB158236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.xctest */,
204 | );
205 | name = Products;
206 | sourceTree = "";
207 | };
208 | FD9EB139236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI */ = {
209 | isa = PBXGroup;
210 | children = (
211 | FD9E6FE52953260500979FFF /* StudyGroupEventFetcherForSwiftUIApp.swift */,
212 | FD0506D4236C4A70003260B9 /* Views */,
213 | FD50ECAB23717D1900BC8342 /* ViewModel */,
214 | FD0506CF236C4662003260B9 /* Model */,
215 | FD525C632371338100F9C171 /* Other */,
216 | FD9EB140236C33EF00DD6367 /* Assets.xcassets */,
217 | FD9EB145236C33EF00DD6367 /* LaunchScreen.storyboard */,
218 | FD9EB148236C33EF00DD6367 /* Info.plist */,
219 | FD9EB142236C33EF00DD6367 /* Preview Content */,
220 | );
221 | path = StudyGroupEventFetcherForSwiftUI;
222 | sourceTree = "";
223 | };
224 | FD9EB142236C33EF00DD6367 /* Preview Content */ = {
225 | isa = PBXGroup;
226 | children = (
227 | FD9EB143236C33EF00DD6367 /* Preview Assets.xcassets */,
228 | );
229 | path = "Preview Content";
230 | sourceTree = "";
231 | };
232 | FD9EB150236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests */ = {
233 | isa = PBXGroup;
234 | children = (
235 | FD9EB151236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.swift */,
236 | FD9EB153236C33EF00DD6367 /* Info.plist */,
237 | );
238 | path = StudyGroupEventFetcherForSwiftUITests;
239 | sourceTree = "";
240 | };
241 | FD9EB15B236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests */ = {
242 | isa = PBXGroup;
243 | children = (
244 | FD9EB15C236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.swift */,
245 | FD9EB15E236C33EF00DD6367 /* Info.plist */,
246 | );
247 | path = StudyGroupEventFetcherForSwiftUIUITests;
248 | sourceTree = "";
249 | };
250 | FDEA053E24ADE2A000AC44EC /* Common */ = {
251 | isa = PBXGroup;
252 | children = (
253 | FDEA053F24ADE2B700AC44EC /* LoadingView.swift */,
254 | FD9E6FD5294D61B000979FFF /* LoadingViewModifier.swift */,
255 | );
256 | path = Common;
257 | sourceTree = "";
258 | };
259 | /* End PBXGroup section */
260 |
261 | /* Begin PBXNativeTarget section */
262 | FD9EB136236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI */ = {
263 | isa = PBXNativeTarget;
264 | buildConfigurationList = FD9EB161236C33EF00DD6367 /* Build configuration list for PBXNativeTarget "StudyGroupEventFetcherForSwiftUI" */;
265 | buildPhases = (
266 | FD9EB133236C33EE00DD6367 /* Sources */,
267 | FD9EB134236C33EE00DD6367 /* Frameworks */,
268 | FD9EB135236C33EE00DD6367 /* Resources */,
269 | );
270 | buildRules = (
271 | );
272 | dependencies = (
273 | );
274 | name = StudyGroupEventFetcherForSwiftUI;
275 | productName = StudyGroupEventFetcherForSwiftUI;
276 | productReference = FD9EB137236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI.app */;
277 | productType = "com.apple.product-type.application";
278 | };
279 | FD9EB14C236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests */ = {
280 | isa = PBXNativeTarget;
281 | buildConfigurationList = FD9EB164236C33EF00DD6367 /* Build configuration list for PBXNativeTarget "StudyGroupEventFetcherForSwiftUITests" */;
282 | buildPhases = (
283 | FD9EB149236C33EF00DD6367 /* Sources */,
284 | FD9EB14A236C33EF00DD6367 /* Frameworks */,
285 | FD9EB14B236C33EF00DD6367 /* Resources */,
286 | );
287 | buildRules = (
288 | );
289 | dependencies = (
290 | FD9EB14F236C33EF00DD6367 /* PBXTargetDependency */,
291 | );
292 | name = StudyGroupEventFetcherForSwiftUITests;
293 | productName = StudyGroupEventFetcherForSwiftUITests;
294 | productReference = FD9EB14D236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.xctest */;
295 | productType = "com.apple.product-type.bundle.unit-test";
296 | };
297 | FD9EB157236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests */ = {
298 | isa = PBXNativeTarget;
299 | buildConfigurationList = FD9EB167236C33EF00DD6367 /* Build configuration list for PBXNativeTarget "StudyGroupEventFetcherForSwiftUIUITests" */;
300 | buildPhases = (
301 | FD9EB154236C33EF00DD6367 /* Sources */,
302 | FD9EB155236C33EF00DD6367 /* Frameworks */,
303 | FD9EB156236C33EF00DD6367 /* Resources */,
304 | );
305 | buildRules = (
306 | );
307 | dependencies = (
308 | FD9EB15A236C33EF00DD6367 /* PBXTargetDependency */,
309 | );
310 | name = StudyGroupEventFetcherForSwiftUIUITests;
311 | productName = StudyGroupEventFetcherForSwiftUIUITests;
312 | productReference = FD9EB158236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.xctest */;
313 | productType = "com.apple.product-type.bundle.ui-testing";
314 | };
315 | /* End PBXNativeTarget section */
316 |
317 | /* Begin PBXProject section */
318 | FD9EB12F236C33EE00DD6367 /* Project object */ = {
319 | isa = PBXProject;
320 | attributes = {
321 | LastSwiftUpdateCheck = 1100;
322 | LastUpgradeCheck = 1100;
323 | ORGANIZATIONNAME = "Takuya Aso";
324 | TargetAttributes = {
325 | FD9EB136236C33EE00DD6367 = {
326 | CreatedOnToolsVersion = 11.0;
327 | };
328 | FD9EB14C236C33EF00DD6367 = {
329 | CreatedOnToolsVersion = 11.0;
330 | TestTargetID = FD9EB136236C33EE00DD6367;
331 | };
332 | FD9EB157236C33EF00DD6367 = {
333 | CreatedOnToolsVersion = 11.0;
334 | TestTargetID = FD9EB136236C33EE00DD6367;
335 | };
336 | };
337 | };
338 | buildConfigurationList = FD9EB132236C33EE00DD6367 /* Build configuration list for PBXProject "StudyGroupEventFetcherForSwiftUI" */;
339 | compatibilityVersion = "Xcode 9.3";
340 | developmentRegion = en;
341 | hasScannedForEncodings = 0;
342 | knownRegions = (
343 | en,
344 | Base,
345 | );
346 | mainGroup = FD9EB12E236C33EE00DD6367;
347 | productRefGroup = FD9EB138236C33EE00DD6367 /* Products */;
348 | projectDirPath = "";
349 | projectRoot = "";
350 | targets = (
351 | FD9EB136236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI */,
352 | FD9EB14C236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests */,
353 | FD9EB157236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests */,
354 | );
355 | };
356 | /* End PBXProject section */
357 |
358 | /* Begin PBXResourcesBuildPhase section */
359 | FD9EB135236C33EE00DD6367 /* Resources */ = {
360 | isa = PBXResourcesBuildPhase;
361 | buildActionMask = 2147483647;
362 | files = (
363 | FD9EB147236C33EF00DD6367 /* LaunchScreen.storyboard in Resources */,
364 | FD9EB144236C33EF00DD6367 /* Preview Assets.xcassets in Resources */,
365 | FD9EB141236C33EF00DD6367 /* Assets.xcassets in Resources */,
366 | );
367 | runOnlyForDeploymentPostprocessing = 0;
368 | };
369 | FD9EB14B236C33EF00DD6367 /* Resources */ = {
370 | isa = PBXResourcesBuildPhase;
371 | buildActionMask = 2147483647;
372 | files = (
373 | );
374 | runOnlyForDeploymentPostprocessing = 0;
375 | };
376 | FD9EB156236C33EF00DD6367 /* Resources */ = {
377 | isa = PBXResourcesBuildPhase;
378 | buildActionMask = 2147483647;
379 | files = (
380 | );
381 | runOnlyForDeploymentPostprocessing = 0;
382 | };
383 | /* End PBXResourcesBuildPhase section */
384 |
385 | /* Begin PBXSourcesBuildPhase section */
386 | FD9EB133236C33EE00DD6367 /* Sources */ = {
387 | isa = PBXSourcesBuildPhase;
388 | buildActionMask = 2147483647;
389 | files = (
390 | FDF7EB90244B2B3000BF1A6E /* EventDetailButtonView.swift in Sources */,
391 | FD9E6FDE29504D5A00979FFF /* PinItem.swift in Sources */,
392 | FD0506D8236C4FA5003260B9 /* EventRowView.swift in Sources */,
393 | FDAE1B78237173C900217BD1 /* StudyGroupDateFormatter.swift in Sources */,
394 | FDEA054024ADE2B700AC44EC /* LoadingView.swift in Sources */,
395 | FD50ECAD23717D3B00BC8342 /* TopListViewModel.swift in Sources */,
396 | FD9E6FD6294D61B000979FFF /* LoadingViewModifier.swift in Sources */,
397 | FD0506D1236C46A4003260B9 /* StudyGroup.swift in Sources */,
398 | FD0506D6236C4A8F003260B9 /* TopListView.swift in Sources */,
399 | FD794B6D2462D35B00C000CD /* EventDetailMapButtonView.swift in Sources */,
400 | FD0506DC2371282C003260B9 /* SafariView.swift in Sources */,
401 | FD9E6FE62953260500979FFF /* StudyGroupEventFetcherForSwiftUIApp.swift in Sources */,
402 | FD9E6FE029504FE000979FFF /* NewMapView.swift in Sources */,
403 | FD0506D3236C471E003260B9 /* Event.swift in Sources */,
404 | FDA2705C24A7873A009A8505 /* EventLabelView.swift in Sources */,
405 | FD0506DA23712219003260B9 /* EventDetailView.swift in Sources */,
406 | FD525C65237133AE00F9C171 /* StudyGroupEventFetcher.swift in Sources */,
407 | FD50073623AFBEEE00C369EF /* EventDetailPartView.swift in Sources */,
408 | FD9E6FE42952BB3400979FFF /* APIError.swift in Sources */,
409 | );
410 | runOnlyForDeploymentPostprocessing = 0;
411 | };
412 | FD9EB149236C33EF00DD6367 /* Sources */ = {
413 | isa = PBXSourcesBuildPhase;
414 | buildActionMask = 2147483647;
415 | files = (
416 | FD9EB152236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUITests.swift in Sources */,
417 | );
418 | runOnlyForDeploymentPostprocessing = 0;
419 | };
420 | FD9EB154236C33EF00DD6367 /* Sources */ = {
421 | isa = PBXSourcesBuildPhase;
422 | buildActionMask = 2147483647;
423 | files = (
424 | FD9EB15D236C33EF00DD6367 /* StudyGroupEventFetcherForSwiftUIUITests.swift in Sources */,
425 | );
426 | runOnlyForDeploymentPostprocessing = 0;
427 | };
428 | /* End PBXSourcesBuildPhase section */
429 |
430 | /* Begin PBXTargetDependency section */
431 | FD9EB14F236C33EF00DD6367 /* PBXTargetDependency */ = {
432 | isa = PBXTargetDependency;
433 | target = FD9EB136236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI */;
434 | targetProxy = FD9EB14E236C33EF00DD6367 /* PBXContainerItemProxy */;
435 | };
436 | FD9EB15A236C33EF00DD6367 /* PBXTargetDependency */ = {
437 | isa = PBXTargetDependency;
438 | target = FD9EB136236C33EE00DD6367 /* StudyGroupEventFetcherForSwiftUI */;
439 | targetProxy = FD9EB159236C33EF00DD6367 /* PBXContainerItemProxy */;
440 | };
441 | /* End PBXTargetDependency section */
442 |
443 | /* Begin PBXVariantGroup section */
444 | FD9EB145236C33EF00DD6367 /* LaunchScreen.storyboard */ = {
445 | isa = PBXVariantGroup;
446 | children = (
447 | FD9EB146236C33EF00DD6367 /* Base */,
448 | );
449 | name = LaunchScreen.storyboard;
450 | sourceTree = "";
451 | };
452 | /* End PBXVariantGroup section */
453 |
454 | /* Begin XCBuildConfiguration section */
455 | FD9EB15F236C33EF00DD6367 /* Debug */ = {
456 | isa = XCBuildConfiguration;
457 | buildSettings = {
458 | ALWAYS_SEARCH_USER_PATHS = NO;
459 | CLANG_ANALYZER_NONNULL = YES;
460 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
461 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
462 | CLANG_CXX_LIBRARY = "libc++";
463 | CLANG_ENABLE_MODULES = YES;
464 | CLANG_ENABLE_OBJC_ARC = YES;
465 | CLANG_ENABLE_OBJC_WEAK = YES;
466 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
467 | CLANG_WARN_BOOL_CONVERSION = YES;
468 | CLANG_WARN_COMMA = YES;
469 | CLANG_WARN_CONSTANT_CONVERSION = YES;
470 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
471 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
472 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
473 | CLANG_WARN_EMPTY_BODY = YES;
474 | CLANG_WARN_ENUM_CONVERSION = YES;
475 | CLANG_WARN_INFINITE_RECURSION = YES;
476 | CLANG_WARN_INT_CONVERSION = YES;
477 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
478 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
479 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
480 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
481 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
482 | CLANG_WARN_STRICT_PROTOTYPES = YES;
483 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
484 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
485 | CLANG_WARN_UNREACHABLE_CODE = YES;
486 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
487 | COPY_PHASE_STRIP = NO;
488 | DEBUG_INFORMATION_FORMAT = dwarf;
489 | ENABLE_STRICT_OBJC_MSGSEND = YES;
490 | ENABLE_TESTABILITY = YES;
491 | GCC_C_LANGUAGE_STANDARD = gnu11;
492 | GCC_DYNAMIC_NO_PIC = NO;
493 | GCC_NO_COMMON_BLOCKS = YES;
494 | GCC_OPTIMIZATION_LEVEL = 0;
495 | GCC_PREPROCESSOR_DEFINITIONS = (
496 | "DEBUG=1",
497 | "$(inherited)",
498 | );
499 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
500 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
501 | GCC_WARN_UNDECLARED_SELECTOR = YES;
502 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
503 | GCC_WARN_UNUSED_FUNCTION = YES;
504 | GCC_WARN_UNUSED_VARIABLE = YES;
505 | IPHONEOS_DEPLOYMENT_TARGET = 16.0;
506 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
507 | MTL_FAST_MATH = YES;
508 | ONLY_ACTIVE_ARCH = YES;
509 | SDKROOT = iphoneos;
510 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
511 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
512 | };
513 | name = Debug;
514 | };
515 | FD9EB160236C33EF00DD6367 /* Release */ = {
516 | isa = XCBuildConfiguration;
517 | buildSettings = {
518 | ALWAYS_SEARCH_USER_PATHS = NO;
519 | CLANG_ANALYZER_NONNULL = YES;
520 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
521 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
522 | CLANG_CXX_LIBRARY = "libc++";
523 | CLANG_ENABLE_MODULES = YES;
524 | CLANG_ENABLE_OBJC_ARC = YES;
525 | CLANG_ENABLE_OBJC_WEAK = YES;
526 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
527 | CLANG_WARN_BOOL_CONVERSION = YES;
528 | CLANG_WARN_COMMA = YES;
529 | CLANG_WARN_CONSTANT_CONVERSION = YES;
530 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
531 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
532 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
533 | CLANG_WARN_EMPTY_BODY = YES;
534 | CLANG_WARN_ENUM_CONVERSION = YES;
535 | CLANG_WARN_INFINITE_RECURSION = YES;
536 | CLANG_WARN_INT_CONVERSION = YES;
537 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
538 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
539 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
540 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
541 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
542 | CLANG_WARN_STRICT_PROTOTYPES = YES;
543 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
544 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
545 | CLANG_WARN_UNREACHABLE_CODE = YES;
546 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
547 | COPY_PHASE_STRIP = NO;
548 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
549 | ENABLE_NS_ASSERTIONS = NO;
550 | ENABLE_STRICT_OBJC_MSGSEND = YES;
551 | GCC_C_LANGUAGE_STANDARD = gnu11;
552 | GCC_NO_COMMON_BLOCKS = YES;
553 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
554 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
555 | GCC_WARN_UNDECLARED_SELECTOR = YES;
556 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
557 | GCC_WARN_UNUSED_FUNCTION = YES;
558 | GCC_WARN_UNUSED_VARIABLE = YES;
559 | IPHONEOS_DEPLOYMENT_TARGET = 16.0;
560 | MTL_ENABLE_DEBUG_INFO = NO;
561 | MTL_FAST_MATH = YES;
562 | SDKROOT = iphoneos;
563 | SWIFT_COMPILATION_MODE = wholemodule;
564 | SWIFT_OPTIMIZATION_LEVEL = "-O";
565 | VALIDATE_PRODUCT = YES;
566 | };
567 | name = Release;
568 | };
569 | FD9EB162236C33EF00DD6367 /* Debug */ = {
570 | isa = XCBuildConfiguration;
571 | buildSettings = {
572 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
573 | CODE_SIGN_STYLE = Automatic;
574 | DEVELOPMENT_ASSET_PATHS = "\"StudyGroupEventFetcherForSwiftUI/Preview Content\"";
575 | DEVELOPMENT_TEAM = 7M7ZGYSAKB;
576 | ENABLE_PREVIEWS = YES;
577 | INFOPLIST_FILE = StudyGroupEventFetcherForSwiftUI/Info.plist;
578 | LD_RUNPATH_SEARCH_PATHS = (
579 | "$(inherited)",
580 | "@executable_path/Frameworks",
581 | );
582 | MARKETING_VERSION = 1.1.0;
583 | PRODUCT_BUNDLE_IDENTIFIER = com.ASTK.StudyGroupEventFetcherForSwiftUI;
584 | PRODUCT_NAME = "$(TARGET_NAME)";
585 | SWIFT_VERSION = 5.0;
586 | TARGETED_DEVICE_FAMILY = "1,2";
587 | };
588 | name = Debug;
589 | };
590 | FD9EB163236C33EF00DD6367 /* Release */ = {
591 | isa = XCBuildConfiguration;
592 | buildSettings = {
593 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
594 | CODE_SIGN_STYLE = Automatic;
595 | DEVELOPMENT_ASSET_PATHS = "\"StudyGroupEventFetcherForSwiftUI/Preview Content\"";
596 | DEVELOPMENT_TEAM = 7M7ZGYSAKB;
597 | ENABLE_PREVIEWS = YES;
598 | INFOPLIST_FILE = StudyGroupEventFetcherForSwiftUI/Info.plist;
599 | LD_RUNPATH_SEARCH_PATHS = (
600 | "$(inherited)",
601 | "@executable_path/Frameworks",
602 | );
603 | MARKETING_VERSION = 1.1.0;
604 | PRODUCT_BUNDLE_IDENTIFIER = com.ASTK.StudyGroupEventFetcherForSwiftUI;
605 | PRODUCT_NAME = "$(TARGET_NAME)";
606 | SWIFT_VERSION = 5.0;
607 | TARGETED_DEVICE_FAMILY = "1,2";
608 | };
609 | name = Release;
610 | };
611 | FD9EB165236C33EF00DD6367 /* Debug */ = {
612 | isa = XCBuildConfiguration;
613 | buildSettings = {
614 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
615 | BUNDLE_LOADER = "$(TEST_HOST)";
616 | CODE_SIGN_STYLE = Automatic;
617 | DEVELOPMENT_TEAM = 7M7ZGYSAKB;
618 | INFOPLIST_FILE = StudyGroupEventFetcherForSwiftUITests/Info.plist;
619 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
620 | LD_RUNPATH_SEARCH_PATHS = (
621 | "$(inherited)",
622 | "@executable_path/Frameworks",
623 | "@loader_path/Frameworks",
624 | );
625 | PRODUCT_BUNDLE_IDENTIFIER = com.ASTK.StudyGroupEventFetcherForSwiftUITests;
626 | PRODUCT_NAME = "$(TARGET_NAME)";
627 | SWIFT_VERSION = 5.0;
628 | TARGETED_DEVICE_FAMILY = "1,2";
629 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StudyGroupEventFetcherForSwiftUI.app/StudyGroupEventFetcherForSwiftUI";
630 | };
631 | name = Debug;
632 | };
633 | FD9EB166236C33EF00DD6367 /* Release */ = {
634 | isa = XCBuildConfiguration;
635 | buildSettings = {
636 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
637 | BUNDLE_LOADER = "$(TEST_HOST)";
638 | CODE_SIGN_STYLE = Automatic;
639 | DEVELOPMENT_TEAM = 7M7ZGYSAKB;
640 | INFOPLIST_FILE = StudyGroupEventFetcherForSwiftUITests/Info.plist;
641 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
642 | LD_RUNPATH_SEARCH_PATHS = (
643 | "$(inherited)",
644 | "@executable_path/Frameworks",
645 | "@loader_path/Frameworks",
646 | );
647 | PRODUCT_BUNDLE_IDENTIFIER = com.ASTK.StudyGroupEventFetcherForSwiftUITests;
648 | PRODUCT_NAME = "$(TARGET_NAME)";
649 | SWIFT_VERSION = 5.0;
650 | TARGETED_DEVICE_FAMILY = "1,2";
651 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StudyGroupEventFetcherForSwiftUI.app/StudyGroupEventFetcherForSwiftUI";
652 | };
653 | name = Release;
654 | };
655 | FD9EB168236C33EF00DD6367 /* Debug */ = {
656 | isa = XCBuildConfiguration;
657 | buildSettings = {
658 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
659 | CODE_SIGN_STYLE = Automatic;
660 | DEVELOPMENT_TEAM = 7M7ZGYSAKB;
661 | INFOPLIST_FILE = StudyGroupEventFetcherForSwiftUIUITests/Info.plist;
662 | LD_RUNPATH_SEARCH_PATHS = (
663 | "$(inherited)",
664 | "@executable_path/Frameworks",
665 | "@loader_path/Frameworks",
666 | );
667 | PRODUCT_BUNDLE_IDENTIFIER = com.ASTK.StudyGroupEventFetcherForSwiftUIUITests;
668 | PRODUCT_NAME = "$(TARGET_NAME)";
669 | SWIFT_VERSION = 5.0;
670 | TARGETED_DEVICE_FAMILY = "1,2";
671 | TEST_TARGET_NAME = StudyGroupEventFetcherForSwiftUI;
672 | };
673 | name = Debug;
674 | };
675 | FD9EB169236C33EF00DD6367 /* Release */ = {
676 | isa = XCBuildConfiguration;
677 | buildSettings = {
678 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
679 | CODE_SIGN_STYLE = Automatic;
680 | DEVELOPMENT_TEAM = 7M7ZGYSAKB;
681 | INFOPLIST_FILE = StudyGroupEventFetcherForSwiftUIUITests/Info.plist;
682 | LD_RUNPATH_SEARCH_PATHS = (
683 | "$(inherited)",
684 | "@executable_path/Frameworks",
685 | "@loader_path/Frameworks",
686 | );
687 | PRODUCT_BUNDLE_IDENTIFIER = com.ASTK.StudyGroupEventFetcherForSwiftUIUITests;
688 | PRODUCT_NAME = "$(TARGET_NAME)";
689 | SWIFT_VERSION = 5.0;
690 | TARGETED_DEVICE_FAMILY = "1,2";
691 | TEST_TARGET_NAME = StudyGroupEventFetcherForSwiftUI;
692 | };
693 | name = Release;
694 | };
695 | /* End XCBuildConfiguration section */
696 |
697 | /* Begin XCConfigurationList section */
698 | FD9EB132236C33EE00DD6367 /* Build configuration list for PBXProject "StudyGroupEventFetcherForSwiftUI" */ = {
699 | isa = XCConfigurationList;
700 | buildConfigurations = (
701 | FD9EB15F236C33EF00DD6367 /* Debug */,
702 | FD9EB160236C33EF00DD6367 /* Release */,
703 | );
704 | defaultConfigurationIsVisible = 0;
705 | defaultConfigurationName = Release;
706 | };
707 | FD9EB161236C33EF00DD6367 /* Build configuration list for PBXNativeTarget "StudyGroupEventFetcherForSwiftUI" */ = {
708 | isa = XCConfigurationList;
709 | buildConfigurations = (
710 | FD9EB162236C33EF00DD6367 /* Debug */,
711 | FD9EB163236C33EF00DD6367 /* Release */,
712 | );
713 | defaultConfigurationIsVisible = 0;
714 | defaultConfigurationName = Release;
715 | };
716 | FD9EB164236C33EF00DD6367 /* Build configuration list for PBXNativeTarget "StudyGroupEventFetcherForSwiftUITests" */ = {
717 | isa = XCConfigurationList;
718 | buildConfigurations = (
719 | FD9EB165236C33EF00DD6367 /* Debug */,
720 | FD9EB166236C33EF00DD6367 /* Release */,
721 | );
722 | defaultConfigurationIsVisible = 0;
723 | defaultConfigurationName = Release;
724 | };
725 | FD9EB167236C33EF00DD6367 /* Build configuration list for PBXNativeTarget "StudyGroupEventFetcherForSwiftUIUITests" */ = {
726 | isa = XCConfigurationList;
727 | buildConfigurations = (
728 | FD9EB168236C33EF00DD6367 /* Debug */,
729 | FD9EB169236C33EF00DD6367 /* Release */,
730 | );
731 | defaultConfigurationIsVisible = 0;
732 | defaultConfigurationName = Release;
733 | };
734 | /* End XCConfigurationList section */
735 | };
736 | rootObject = FD9EB12F236C33EE00DD6367 /* Project object */;
737 | }
738 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI.xcodeproj/xcuserdata/milanista.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | StudyGroupEventFetcherForSwiftUI.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "app_icon40.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "app_icon60.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "app_icon58.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "app_icon87.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "40x40",
29 | "idiom" : "iphone",
30 | "filename" : "app_icon80.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "app_icon120.png",
37 | "scale" : "3x"
38 | },
39 | {
40 | "size" : "60x60",
41 | "idiom" : "iphone",
42 | "filename" : "app_icon120-1.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "app_icon180.png",
49 | "scale" : "3x"
50 | },
51 | {
52 | "size" : "20x20",
53 | "idiom" : "ipad",
54 | "filename" : "app_icon20.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "app_icon40-1.png",
61 | "scale" : "2x"
62 | },
63 | {
64 | "size" : "29x29",
65 | "idiom" : "ipad",
66 | "filename" : "app_icon29.png",
67 | "scale" : "1x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "app_icon58-1.png",
73 | "scale" : "2x"
74 | },
75 | {
76 | "size" : "40x40",
77 | "idiom" : "ipad",
78 | "filename" : "app_icon40-2.png",
79 | "scale" : "1x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "app_icon80-1.png",
85 | "scale" : "2x"
86 | },
87 | {
88 | "size" : "76x76",
89 | "idiom" : "ipad",
90 | "filename" : "app_icon76.png",
91 | "scale" : "1x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "app_icon152.png",
97 | "scale" : "2x"
98 | },
99 | {
100 | "size" : "83.5x83.5",
101 | "idiom" : "ipad",
102 | "filename" : "app_icon167.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "1024x1024",
107 | "idiom" : "ios-marketing",
108 | "filename" : "app_icon1024.png",
109 | "scale" : "1x"
110 | }
111 | ],
112 | "info" : {
113 | "version" : 1,
114 | "author" : "xcode"
115 | }
116 | }
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon1024.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon120-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon120-1.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon120.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon152.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon167.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon180.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon20.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon29.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon40-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon40-1.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon40-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon40-2.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon40.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon58-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon58-1.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon58.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon60.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon76.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon80-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon80-1.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon80.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/AppIcon.appiconset/app_icon87.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/Detail/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/Detail/img_yumemi_swift.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "img_yumemi_swift.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/Detail/img_yumemi_swift.imageset/img_yumemi_swift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MilanistaDev/StudyGroupEventFetcherForSwiftUI/417935cd89d121bbcaae2d2c8138deffe4927b41/StudyGroupEventFetcherForSwiftUI/Assets.xcassets/Detail/img_yumemi_swift.imageset/img_yumemi_swift.png
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 |
28 | UILaunchStoryboardName
29 | LaunchScreen
30 | UIRequiredDeviceCapabilities
31 |
32 | armv7
33 |
34 | UISupportedInterfaceOrientations
35 |
36 | UIInterfaceOrientationPortrait
37 |
38 | UISupportedInterfaceOrientations~ipad
39 |
40 | UIInterfaceOrientationPortrait
41 | UIInterfaceOrientationPortraitUpsideDown
42 | UIInterfaceOrientationLandscapeLeft
43 | UIInterfaceOrientationLandscapeRight
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Model/Event.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Event.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/01.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Event: Decodable, Identifiable, Hashable {
12 | var id: Int
13 | var title: String
14 | var subTitle: String
15 | var eventUrl: String
16 | var hashTag: String
17 | var startDate: String
18 | var endDate: String
19 | var place: String
20 | var address: String
21 | var lat: String?
22 | var lon: String?
23 | var ownerDisplayName: String
24 |
25 | enum CodingKeys: String, CodingKey {
26 | case id = "event_id"
27 | case title = "title"
28 | case subTitle = "catch"
29 | case eventUrl = "event_url"
30 | case hashTag = "hash_tag"
31 | case startDate = "started_at"
32 | case endDate = "ended_at"
33 | case place = "place"
34 | case address = "address"
35 | case lat = "lat"
36 | case lon = "lon"
37 | case ownerDisplayName = "owner_display_name"
38 | }
39 | }
40 |
41 | // Reference of API
42 | // Event Search API
43 | // https://connpass.com/about/api/
44 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Model/PinItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PinItem.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2022/12/19.
6 | // Copyright © 2022 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import MapKit
11 |
12 | struct PinItem: Identifiable {
13 | let id = UUID()
14 | let coordinate: CLLocationCoordinate2D
15 | }
16 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Model/StudyGroup.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StudyGroup.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/01.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct StudyGroup: Decodable {
12 | var events: [Event]
13 | }
14 |
15 | // Reference of API
16 | // Event Search API
17 | // https://connpass.com/about/api/
18 |
19 | // Sample mock data
20 | let mockEventsData: [Event]
21 | = [Event(id: 1,
22 | title: "YUMEMI.swift #1 ~WWDC19報告会~",
23 | subTitle: "サブタイトル(キャッチ)",
24 | eventUrl: "https://yumemi.connpass.com/event/131175/",
25 | hashTag: "yumemi_swift",
26 | startDate: "2019-06-24T19:00:00+09:00",
27 | endDate: "2019-06-24T21:30:00+09:00",
28 | place: "株式会社ゆめみ",
29 | address: "東京都世田谷区",
30 | lat: "35.641587300000",
31 | lon: "139.669071500000",
32 | ownerDisplayName: "株式会社ゆめみ"),
33 | Event(id: 2,
34 | title: "YUMEMI.swift #1 ~WWDC19報告会~ パプリックビューイング @Sapporo",
35 | subTitle: "サブタイトル(キャッチ)",
36 | eventUrl: "https://yumemi.connpass.com/event/135183/",
37 | hashTag: "yumemi_swift",
38 | startDate: "2019-06-24T19:00:00+09:00",
39 | endDate: "2019-06-24T21:30:00+09:00",
40 | place: "株式会社ゆめみ",
41 | address: "北海道札幌市中央区",
42 | lat: "35.641587300000",
43 | lon: "139.669071500000",
44 | ownerDisplayName: "株式会社ゆめみ"),
45 | Event(id: 3,
46 | title: "Enjoy SwiftUI vol1",
47 | subTitle: "サブタイトル(キャッチ)",
48 | eventUrl: "https://yumemi.connpass.com/event/139079/",
49 | hashTag: "yumemi_swift",
50 | startDate: "2019-07-31T19:00:00+09:00",
51 | endDate: "2019-07-31T21:30:00+09:00",
52 | place: "株式会社ゆめみ",
53 | address: "東京都世田谷区",
54 | lat: "35.641587300000",
55 | lon: "139.669071500000",
56 | ownerDisplayName: "株式会社ゆめみ"),
57 | Event(id: 4,
58 | title: "YUMEMI.swift #3 ~俺/私がやったiOS 13対応~",
59 | subTitle: "サブタイトル(キャッチ)",
60 | eventUrl: "https://yumemi.connpass.com/event/142608/",
61 | hashTag: "yumemi_swift",
62 | startDate: "2019-09-30T19:00:00+09:00",
63 | endDate: "2019-09-30T21:30:00+09:00",
64 | place: "株式会社ゆめみ",
65 | address: "東京都世田谷区",
66 | lat: "35.641587300000",
67 | lon: "139.669071500000",
68 | ownerDisplayName: "株式会社ゆめみ"),
69 | Event(id: 5,
70 | title: "Enjoy SwiftUI vol2",
71 | subTitle: "サブタイトル(キャッチ)",
72 | eventUrl: "https://yumemi.connpass.com/event/151594/",
73 | hashTag: "yumemi_swiftui",
74 | startDate: "2019-11-08T19:00:00+09:00",
75 | endDate: "2019-11-08T21:30:00+09:00",
76 | place: "株式会社ゆめみ",
77 | address: "東京都世田谷区",
78 | lat: "35.641587300000",
79 | lon: "139.669071500000",
80 | ownerDisplayName: "株式会社ゆめみ"),
81 | Event(id: 6,
82 | title: "YUMEMI.swift #5",
83 | subTitle: "サブタイトル(キャッチ)",
84 | eventUrl: "",
85 | hashTag: "yumemi_swift",
86 | startDate: "2019-11-29T19:30:00+09:00",
87 | endDate: "2019-11-29T21:30:00+09:00",
88 | place: "株式会社ゆめみ",
89 | address: "東京都世田谷区",
90 | lat: "35.641587300000",
91 | lon: "139.669071500000",
92 | ownerDisplayName: "株式会社ゆめみ")
93 | ]
94 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Other/APIError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // APIError.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2022/12/21.
6 | // Copyright © 2022 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum APIError: Error {
12 | case network
13 | case response
14 | case jsonDecode
15 | case statusCode(statusCode: String)
16 | }
17 |
18 | extension APIError: LocalizedError {
19 | var errorDescription: String? {
20 | switch self {
21 | case .network:
22 | return "Network Error"
23 |
24 | case .response:
25 | return "Response Error"
26 |
27 | case .jsonDecode:
28 | return "json convert failed in JSONDecoder"
29 |
30 | case .statusCode(let statusCode):
31 | return "Error! StatuCode: " + String(statusCode)
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Other/StudyGroupDateFormatter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StudyGroupDateFormatter.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/05.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class StudyGroupDateFormatter: DateFormatter {
12 |
13 | class func convertNormalDateString(dateStr: String, isOnlyDate: Bool) -> String {
14 | let formatter = ISO8601DateFormatter()
15 | let date = formatter.date(from: dateStr)
16 | return convertDateToString(date: date!, isOnlyDate: isOnlyDate)
17 | }
18 |
19 | class func convertDateToString(date: Date, isOnlyDate: Bool) -> String {
20 | let formatter = DateFormatter()
21 | formatter.dateStyle = isOnlyDate ? .none: .short
22 | formatter.timeStyle = .short
23 | formatter.locale = Locale(identifier: "ja_JP")
24 | return formatter.string(from: date)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Other/StudyGroupEventFetcher.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StudyGroupEventFetcher.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/05.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class StudyGroupEventFetcher {
12 |
13 | // connpass's event search API
14 | private let urlLink = "https://connpass.com/api/v1/event/?keyword=YUMEMI.swift&count=100"
15 |
16 | func fetchEventData() async throws -> [Event] {
17 | let (data, response) = try await URLSession.shared.data(from: URL(string: urlLink)!)
18 |
19 | guard let httpResponse = response as? HTTPURLResponse else {
20 | throw APIError.response
21 | }
22 |
23 | switch httpResponse.statusCode {
24 | case 200:
25 | do {
26 | let searchedResultData = try JSONDecoder().decode(StudyGroup.self, from: data)
27 | return searchedResultData.events.reversed()
28 |
29 | } catch {
30 | throw APIError.jsonDecode
31 | }
32 |
33 | default:
34 | throw APIError.statusCode(statusCode: httpResponse.statusCode.description)
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/StudyGroupEventFetcherForSwiftUIApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StudyGroupEventFetcherForSwiftUIApp.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2022/12/21.
6 | // Copyright © 2022 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | @main
12 | struct StudyGroupEventFetcherForSwiftUIApp: App {
13 | var body: some Scene {
14 | WindowGroup {
15 | TopListView()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/ViewModel/TopListViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TopListViewModel.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/05.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class TopListViewModel: ObservableObject {
12 | @Published var eventData: [Event] = []
13 | @Published var isShowIndicator = false
14 | @Published var error: APIError?
15 | @Published var isShowAlert = false
16 |
17 | private let fetcher = StudyGroupEventFetcher()
18 |
19 | /// 勉強会データをAPIを叩いて取得(async/await版)
20 | func fetchEventData() {
21 | Task { @MainActor in
22 | isShowIndicator = true
23 | defer {
24 | isShowIndicator = false
25 | }
26 | try? await Task.sleep(nanoseconds: 1_000_000_000)
27 |
28 | do {
29 | eventData = try await fetcher.fetchEventData()
30 |
31 | } catch {
32 | if let apiError = error as? APIError {
33 | self.error = apiError
34 | isShowAlert = true
35 | } else if let error = error as? URLError, error.code == URLError.notConnectedToInternet {
36 | self.error = APIError.network
37 | isShowAlert = true
38 | } else {
39 | // 🤔
40 | print(error.localizedDescription)
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/Common/LoadingView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoadingView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2020/07/02.
6 | // Copyright © 2020 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct LoadingView: View {
12 | var body: some View {
13 | ZStack {
14 | RoundedRectangle(cornerRadius: 10.0)
15 | .fill(Color.gray)
16 | .frame(width: 100.0, height: 100.0, alignment: .center)
17 | VStack {
18 | Text("💫")
19 | .padding(.bottom, 10.0)
20 | .font(.title)
21 | Text("Loading...")
22 | .font(.body)
23 | .bold()
24 | .foregroundColor(.white)
25 | }
26 | }
27 | }
28 | }
29 | struct LoadingView_Previews: PreviewProvider {
30 | static var previews: some View {
31 | LoadingView()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/Common/LoadingViewModifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoadingViewModifier.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2022/12/17.
6 | // Copyright © 2022 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | /// ローディング画面を出すViewModifier
12 | struct LoadingViewModifier: ViewModifier {
13 | var isRefreshing: Bool
14 |
15 | func body(content: Content) -> some View {
16 | ZStack {
17 | content
18 | .allowsHitTesting(!isRefreshing)
19 |
20 | if isRefreshing {
21 | ProgressView {
22 | Text("Loading...")
23 | }
24 | }
25 | }
26 | }
27 | }
28 |
29 | extension View {
30 | /// 通信中にProgressViewを表示
31 | /// - Parameters:
32 | /// - isRefreshing: 通信中か
33 | /// - Returns: ローディング画面
34 | func loading(isRefreshing: Bool, safeAreaEdges: Edge.Set = []) -> some View {
35 | modifier(LoadingViewModifier(isRefreshing: isRefreshing))
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/EventDetail/EventDetailButtonView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EventDetailButtonView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by 麻生 拓弥 on 2020/04/18.
6 | // Copyright © 2020 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct EventDetailButtonView: View {
12 |
13 | let eventUrl: String
14 |
15 | var body: some View {
16 | if #available(iOS 14.0, *) {
17 | return AnyView(EventLinkView(eventUrl: self.eventUrl))
18 | } else {
19 | return AnyView(EventLinkButton(eventUrl: self.eventUrl))
20 | }
21 | }
22 | }
23 |
24 | /// iOS 14 で Link を使って Safari を開くボタン
25 | @available(iOS 14.0, *)
26 | struct EventLinkView: View {
27 | var eventUrl: String
28 | var body: some View {
29 | Link(destination: URL(string: self.eventUrl)!) {
30 | EventDetailButtonTitleView()
31 | }.padding(20.0)
32 | }
33 | }
34 |
35 | /// iOS 13 で SafariVC を開くボタン
36 | struct EventLinkButton: View {
37 | var eventUrl: String
38 | @State private var showModal = false
39 | var body: some View {
40 | Button(action: {
41 | self.showModal.toggle()
42 | }) {
43 | EventDetailButtonTitleView()
44 | }
45 | .sheet(isPresented: $showModal) {
46 | SafariView(url: URL(string: self.eventUrl))
47 | .edgesIgnoringSafeArea(.bottom)
48 | }.padding(20.0)
49 | }
50 | }
51 |
52 | struct EventDetailButtonTitleView: View {
53 | var body: some View {
54 | Text("connpassのイベントページ")
55 | .frame(minWidth: 0, maxWidth: .infinity)
56 | .padding()
57 | .font(Font.body.bold())
58 | .foregroundColor(.white)
59 | .background(Color.red)
60 | .cornerRadius(5.0)
61 | }
62 | }
63 | struct EventDetailButtonView_Previews: PreviewProvider {
64 | static var previews: some View {
65 | EventDetailButtonView(eventUrl: mockEventsData[0].eventUrl)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/EventDetail/EventDetailMapButtonView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EventDetailMapButtonView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2020/05/06.
6 | // Copyright © 2020 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct EventDetailMapButtonView: View {
12 |
13 | @Binding var zoomValue: Double
14 |
15 | var body: some View {
16 | VStack {
17 | Button(action: {
18 | // マップ拡大
19 | self.zoomValue *= 0.5
20 | }) {
21 | Image(systemName: "plus.app.fill")
22 | .resizable()
23 | .frame(width: 30.0, height: 30.0)
24 | .foregroundColor(.gray)
25 | }
26 | Button(action: {
27 | // マップ縮小
28 | self.zoomValue *= 2
29 | }) {
30 | Image(systemName: "minus.square.fill")
31 | .resizable()
32 | .frame(width: 30.0, height: 30.0)
33 | .foregroundColor(.gray)
34 | }
35 | }
36 | }
37 | }
38 |
39 | struct EventDetailMapButtonView_Previews: PreviewProvider {
40 | static var previews: some View {
41 | EventDetailMapButtonView(zoomValue: .constant(0.01))
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/EventDetail/EventDetailPartView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EventDetailPartView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/12/23.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct EventDetailPartView: View {
12 | // Event Model
13 | let eventData: Event
14 |
15 | var body: some View {
16 | VStack(alignment: .leading) {
17 | Text(eventData.title)
18 | .font(.headline)
19 | .lineLimit(2)
20 | .fixedSize(horizontal: false, vertical: true)
21 | .padding(.vertical, 8.0)
22 | Text(eventData.subTitle)
23 | .font(.caption)
24 | .foregroundColor(.gray)
25 | .lineLimit(3)
26 | .fixedSize(horizontal: false, vertical: true)
27 | .padding(.bottom, 24.0)
28 | Text(eventData.place)
29 | .font(.headline)
30 | .lineLimit(2)
31 | .fixedSize(horizontal: false, vertical: true)
32 | .padding(.bottom, 12.0)
33 | Text(eventData.address)
34 | .font(.footnote)
35 | .lineLimit(2)
36 | .fixedSize(horizontal: false, vertical: true)
37 | .padding(.bottom, 24.0)
38 | Text(StudyGroupDateFormatter.convertNormalDateString(dateStr: eventData.startDate, isOnlyDate: false) + " ~ " + StudyGroupDateFormatter.convertNormalDateString(dateStr: eventData.endDate, isOnlyDate: true))
39 | .font(.subheadline)
40 | .padding(.bottom, 48.0)
41 | }
42 | .padding(.horizontal, 20.0)
43 | }
44 | }
45 |
46 | struct EventDetailPartView_Previews: PreviewProvider {
47 | static var previews: some View {
48 | EventDetailPartView(eventData: mockEventsData[0])
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/EventDetail/EventDetailView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EventDetailView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/05.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct EventDetailView: View {
12 | let eventData: Event // From ListView(静的モデル)
13 | @State private var zoomValue = 0.01
14 |
15 | var body: some View {
16 | ScrollView {
17 | VStack(alignment: .leading) {
18 | // MapView Part
19 | ZStack(alignment: .bottomTrailing) {
20 | NewMapView(
21 | eventData: eventData,
22 | zoomValue: $zoomValue
23 | )
24 | .frame(height: 300.0)
25 |
26 | EventDetailMapButtonView(zoomValue: $zoomValue)
27 | .padding(.bottom, 24.0)
28 | .padding(.trailing, 12.0)
29 | }
30 | // Event detail part
31 | EventDetailPartView(eventData: self.eventData)
32 | // Bottom button
33 | EventDetailButtonView(eventUrl: self.eventData.eventUrl)
34 | }
35 | }
36 | .navigationTitle("勉強会詳細")
37 | .navigationBarTitleDisplayMode(.inline)
38 | }
39 | }
40 |
41 | struct EventDetailView_Previews: PreviewProvider {
42 | static var previews: some View {
43 | EventDetailView(eventData: mockEventsData[0])
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/Map/NewMapView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NewMapView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2022/12/19.
6 | // Copyright © 2022 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 | import MapKit
11 |
12 | struct NewMapView: View {
13 | // リスト画面から渡ってくる勉強会情報
14 | let eventData: Event
15 | // 詳細画面のマップの右下の+ - ボタンで変わるズームの値
16 | @Binding var zoomValue: CLLocationDegrees
17 |
18 | @State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 35.6816005869028, longitude: 139.76595878344898), span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
19 |
20 | var body: some View {
21 | Map(
22 | coordinateRegion: $region,
23 | annotationItems: generatePinItem()) { item in
24 | MapMarker(coordinate: item.coordinate)
25 | }
26 | .onAppear {
27 | setTargetRegion()
28 | }
29 | .onChange(of: zoomValue) { newValue in
30 | // + - ボタンでズームの値が変わるのでその変化を検知してマップの拡大縮小を行う
31 | region.span = MKCoordinateSpan(latitudeDelta: zoomValue, longitudeDelta: zoomValue)
32 | }
33 | }
34 | }
35 |
36 | extension NewMapView {
37 | /// アノテーション用のデータを生成
38 | private func generatePinItem() -> [PinItem] {
39 | guard let latitude = eventData.lat,
40 | let latValue = Double(latitude),
41 | let longitude = eventData.lon,
42 | let lonValue = Double(longitude) else {
43 | return []
44 | }
45 | return [PinItem(coordinate: CLLocationCoordinate2D(latitude: latValue, longitude: lonValue))]
46 | }
47 |
48 | /// 表示時にマップの中央を会場の場所にする
49 | private func setTargetRegion() {
50 | guard let latitude = eventData.lat,
51 | let latValue = Double(latitude),
52 | let longitude = eventData.lon,
53 | let lonValue = Double(longitude) else {
54 | // オンライン開催などで緯度経度の情報がnilの場合広域にしておく
55 | region.span = MKCoordinateSpan(latitudeDelta: 30, longitudeDelta: 30)
56 | return
57 | }
58 | // マップの中央を会場に
59 | region.center = CLLocationCoordinate2D(latitude: latValue, longitude: lonValue)
60 | }
61 | }
62 |
63 | struct NewMapView_Previews: PreviewProvider {
64 | static var previews: some View {
65 | NewMapView(eventData: mockEventsData[0], zoomValue: .constant(0.01))
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/Safari/SafariView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SafariView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/05.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 | import SafariServices
11 |
12 | struct SafariView: UIViewControllerRepresentable {
13 | typealias UIViewControllerType = SFSafariViewController
14 |
15 | var url: URL?
16 |
17 | func makeUIViewController(context: UIViewControllerRepresentableContext) -> SFSafariViewController {
18 | return SFSafariViewController(url: url!)
19 | }
20 |
21 | func updateUIViewController(_ safariViewController: SFSafariViewController, context: UIViewControllerRepresentableContext) {
22 | }
23 | }
24 |
25 | struct SafariView_Previews: PreviewProvider {
26 | static var previews: some View {
27 | SafariView(url: URL(string: mockEventsData[0].eventUrl)!)
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/TopEventList/EventLabelView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EventLabelView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2020/06/27.
6 | // Copyright © 2020 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | enum ColorType {
12 | case multiColor
13 | case monochrome
14 | }
15 |
16 | struct EventLabelView: View {
17 |
18 | let labelName: String
19 | let iconName: String
20 | let colorType: ColorType
21 |
22 | var body: some View {
23 | HStack {
24 | switch colorType {
25 | case .monochrome:
26 | Image(systemName: iconName)
27 | .imageScale(.medium)
28 | .foregroundColor(.red)
29 | case .multiColor:
30 | if #available(iOS 14.0, *) {
31 | Image(systemName: iconName)
32 | .renderingMode(.original)
33 | .imageScale(.medium)
34 | } else {
35 | Image(systemName: iconName)
36 | .imageScale(.medium)
37 | .foregroundColor(.red)
38 | }
39 | }
40 | Text(labelName)
41 | .font(.footnote)
42 | .lineLimit(3)
43 | .fixedSize(horizontal: false, vertical: true)
44 | }.padding(.bottom, 6.0)
45 | }
46 | }
47 |
48 | struct EventLabelView_Previews: PreviewProvider {
49 | static var previews: some View {
50 | EventLabelView(labelName: mockEventsData[0].address,
51 | iconName: "mappin.circle.fill",
52 | colorType: .multiColor)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/TopEventList/EventRowView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EventRowView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/01.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct EventRowView: View {
12 |
13 | let eventData: Event
14 |
15 | var body: some View {
16 | VStack(alignment: .leading) {
17 | Text(eventData.title)
18 | .bold()
19 | .font(.headline)
20 | .lineLimit(2)
21 | .fixedSize(horizontal: false, vertical: true)
22 | .padding(.vertical, 8.0)
23 | EventLabelView(
24 | labelName: StudyGroupDateFormatter.convertNormalDateString(dateStr: eventData.startDate, isOnlyDate: false) + "~",
25 | iconName: "calendar.circle.fill",
26 | colorType: .multiColor)
27 | EventLabelView(labelName: eventData.ownerDisplayName + " 他",
28 | iconName: "person.fill",
29 | colorType: .monochrome)
30 | EventLabelView(labelName: eventData.address,
31 | iconName: "mappin.circle.fill",
32 | colorType: .multiColor)
33 | HStack {
34 | Spacer()
35 | Text("#" + eventData.hashTag)
36 | .foregroundColor(.blue)
37 | .font(.caption)
38 | .bold()
39 | .padding(.horizontal, 8.0)
40 | .padding(.vertical, 4.0)
41 | .overlay(
42 | RoundedRectangle(cornerRadius: 20.0)
43 | .stroke(Color.blue, lineWidth: 1.0)
44 | )
45 | }
46 | .padding(.bottom, 8.0)
47 | }
48 | }
49 | }
50 |
51 | struct EventRowView_Previews: PreviewProvider {
52 | static var previews: some View {
53 | EventRowView(eventData: mockEventsData[0])
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUI/Views/TopEventList/TopListView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TopListView.swift
3 | // StudyGroupEventFetcherForSwiftUI
4 | //
5 | // Created by Takuya Aso on 2019/11/01.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct TopListView: View {
12 | @StateObject private var topListVM = TopListViewModel()
13 |
14 | var body: some View {
15 | NavigationStack {
16 | List(topListVM.eventData) { event in
17 | NavigationLink(value: event) {
18 | EventRowView(eventData: event)
19 | }
20 | }
21 | .navigationDestination(for: Event.self) { event in
22 | EventDetailView(eventData: event)
23 | }
24 | .navigationTitle("YUMEMI.swift一覧")
25 | .navigationBarTitleDisplayMode(.large)
26 | .loading(isRefreshing: topListVM.isShowIndicator)
27 | }
28 | .onAppear {
29 | topListVM.fetchEventData()
30 | }
31 | .alert(isPresented: $topListVM.isShowAlert, error: topListVM.error) { _ in
32 | Button("OK", action: {})
33 | } message: { error in
34 | Text(error.errorDescription ?? "なぜかnilみたいね")
35 | }
36 | }
37 | }
38 |
39 | struct TopListView_Previews: PreviewProvider {
40 | static var previews: some View {
41 | TopListView()
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUITests/StudyGroupEventFetcherForSwiftUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StudyGroupEventFetcherForSwiftUITests.swift
3 | // StudyGroupEventFetcherForSwiftUITests
4 | //
5 | // Created by Takuya Aso on 2019/11/01.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import StudyGroupEventFetcherForSwiftUI
11 |
12 | class StudyGroupEventFetcherForSwiftUITests: XCTestCase {
13 |
14 | override func setUp() {
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | }
21 |
22 | func testExample() {
23 | // This is an example of a functional test case.
24 | // Use XCTAssert and related functions to verify your tests produce the correct results.
25 | }
26 |
27 | func testPerformanceExample() {
28 | // This is an example of a performance test case.
29 | self.measure {
30 | // Put the code you want to measure the time of here.
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUIUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/StudyGroupEventFetcherForSwiftUIUITests/StudyGroupEventFetcherForSwiftUIUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StudyGroupEventFetcherForSwiftUIUITests.swift
3 | // StudyGroupEventFetcherForSwiftUIUITests
4 | //
5 | // Created by Takuya Aso on 2019/11/01.
6 | // Copyright © 2019 Takuya Aso. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class StudyGroupEventFetcherForSwiftUIUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 |
16 | // In UI tests it is usually best to stop immediately when a failure occurs.
17 | continueAfterFailure = false
18 |
19 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
20 | }
21 |
22 | override func tearDown() {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | }
25 |
26 | func testExample() {
27 | // UI tests must launch the application that they test.
28 | let app = XCUIApplication()
29 | app.launch()
30 |
31 | // Use recording to get started writing UI tests.
32 | // Use XCTAssert and related functions to verify your tests produce the correct results.
33 | }
34 |
35 | func testLaunchPerformance() {
36 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
37 | // This measures how long it takes to launch your application.
38 | measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) {
39 | XCUIApplication().launch()
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------