Skip to content

Commit c1aa921

Browse files
committed
Add source code for chapter 10
1 parent aba0db0 commit c1aa921

File tree

78 files changed

+3852
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+3852
-0
lines changed

10-networking/0-start/.gitignore

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#### joe made this: https://goel.io/joe
2+
3+
#####=== Swift ===#####
4+
5+
# Xcode
6+
#
7+
build/
8+
*.pbxuser
9+
!default.pbxuser
10+
*.mode1v3
11+
!default.mode1v3
12+
*.mode2v3
13+
!default.mode2v3
14+
*.perspectivev3
15+
!default.perspectivev3
16+
xcuserdata
17+
*.xccheckout
18+
*.moved-aside
19+
DerivedData
20+
*.hmap
21+
*.ipa
22+
*.xcuserstate
23+
24+
# CocoaPods
25+
#
26+
# We recommend against adding the Pods directory to your .gitignore. However
27+
# you should judge for yourself, the pros and cons are mentioned at:
28+
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
29+
#
30+
# Pods/
31+

10-networking/0-start/Albertos.xcodeproj/project.pbxproj

+939
Large diffs are not rendered by default.

10-networking/0-start/Albertos.xcodeproj/project.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1230"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "3FC9D8AC2562389E00BF115D"
18+
BuildableName = "Albertos.app"
19+
BlueprintName = "Albertos"
20+
ReferencedContainer = "container:Albertos.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES">
30+
<Testables>
31+
<TestableReference
32+
skipped = "NO">
33+
<BuildableReference
34+
BuildableIdentifier = "primary"
35+
BlueprintIdentifier = "3FC9D8BD2562389F00BF115D"
36+
BuildableName = "AlbertosTests.xctest"
37+
BlueprintName = "AlbertosTests"
38+
ReferencedContainer = "container:Albertos.xcodeproj">
39+
</BuildableReference>
40+
</TestableReference>
41+
<TestableReference
42+
skipped = "YES">
43+
<BuildableReference
44+
BuildableIdentifier = "primary"
45+
BlueprintIdentifier = "3FC9D8C8256238A000BF115D"
46+
BuildableName = "AlbertosUITests.xctest"
47+
BlueprintName = "AlbertosUITests"
48+
ReferencedContainer = "container:Albertos.xcodeproj">
49+
</BuildableReference>
50+
</TestableReference>
51+
</Testables>
52+
</TestAction>
53+
<LaunchAction
54+
buildConfiguration = "Debug"
55+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
56+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
57+
launchStyle = "0"
58+
useCustomWorkingDirectory = "NO"
59+
ignoresPersistentStateOnLaunch = "NO"
60+
debugDocumentVersioning = "YES"
61+
debugServiceExtension = "internal"
62+
allowLocationSimulation = "YES">
63+
<BuildableProductRunnable
64+
runnableDebuggingMode = "0">
65+
<BuildableReference
66+
BuildableIdentifier = "primary"
67+
BlueprintIdentifier = "3FC9D8AC2562389E00BF115D"
68+
BuildableName = "Albertos.app"
69+
BlueprintName = "Albertos"
70+
ReferencedContainer = "container:Albertos.xcodeproj">
71+
</BuildableReference>
72+
</BuildableProductRunnable>
73+
</LaunchAction>
74+
<ProfileAction
75+
buildConfiguration = "Release"
76+
shouldUseLaunchSchemeArgsEnv = "YES"
77+
savedToolIdentifier = ""
78+
useCustomWorkingDirectory = "NO"
79+
debugDocumentVersioning = "YES">
80+
<BuildableProductRunnable
81+
runnableDebuggingMode = "0">
82+
<BuildableReference
83+
BuildableIdentifier = "primary"
84+
BlueprintIdentifier = "3FC9D8AC2562389E00BF115D"
85+
BuildableName = "Albertos.app"
86+
BlueprintName = "Albertos"
87+
ReferencedContainer = "container:Albertos.xcodeproj">
88+
</BuildableReference>
89+
</BuildableProductRunnable>
90+
</ProfileAction>
91+
<AnalyzeAction
92+
buildConfiguration = "Debug">
93+
</AnalyzeAction>
94+
<ArchiveAction
95+
buildConfiguration = "Release"
96+
revealArchiveInOrganizer = "YES">
97+
</ArchiveAction>
98+
</Scheme>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import SwiftUI
2+
3+
@main
4+
struct AlbertosApp: App {
5+
6+
var body: some Scene {
7+
WindowGroup {
8+
NavigationView {
9+
MenuList(viewModel: .init(menuFetching: MenuFetchingPlaceholder()))
10+
.navigationTitle("Alberto's 🇮🇹")
11+
}
12+
}
13+
}
14+
}
15+
16+
// In this first iteration the menu is an hard-coded array
17+
let menu = [
18+
MenuItem(category: "starters", name: "Caprese Salad", spicy: false, price: 3.0),
19+
MenuItem(category: "starters", name: "Arancini Balls", spicy: false, price: 3.5),
20+
MenuItem(category: "pastas", name: "Penne all'Arrabbiata", spicy: true, price: 8.0),
21+
MenuItem(category: "pastas", name: "Spaghetti Carbonara", spicy: false, price: 9.0),
22+
MenuItem(category: "drinks", name: "Water", spicy: false, price: 1.5),
23+
MenuItem(category: "drinks", name: "Red Wine", spicy: false, price: 4.5),
24+
MenuItem(category: "desserts", name: "Tiramisù", spicy: false, price: 5.0),
25+
MenuItem(category: "desserts", name: "Crema Catalana", spicy: false, price: 4.5),
26+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"colors" : [
3+
{
4+
"idiom" : "universal"
5+
}
6+
],
7+
"info" : {
8+
"author" : "xcode",
9+
"version" : 1
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "iphone",
5+
"scale" : "2x",
6+
"size" : "20x20"
7+
},
8+
{
9+
"idiom" : "iphone",
10+
"scale" : "3x",
11+
"size" : "20x20"
12+
},
13+
{
14+
"idiom" : "iphone",
15+
"scale" : "2x",
16+
"size" : "29x29"
17+
},
18+
{
19+
"idiom" : "iphone",
20+
"scale" : "3x",
21+
"size" : "29x29"
22+
},
23+
{
24+
"idiom" : "iphone",
25+
"scale" : "2x",
26+
"size" : "40x40"
27+
},
28+
{
29+
"idiom" : "iphone",
30+
"scale" : "3x",
31+
"size" : "40x40"
32+
},
33+
{
34+
"idiom" : "iphone",
35+
"scale" : "2x",
36+
"size" : "60x60"
37+
},
38+
{
39+
"idiom" : "iphone",
40+
"scale" : "3x",
41+
"size" : "60x60"
42+
},
43+
{
44+
"idiom" : "ipad",
45+
"scale" : "1x",
46+
"size" : "20x20"
47+
},
48+
{
49+
"idiom" : "ipad",
50+
"scale" : "2x",
51+
"size" : "20x20"
52+
},
53+
{
54+
"idiom" : "ipad",
55+
"scale" : "1x",
56+
"size" : "29x29"
57+
},
58+
{
59+
"idiom" : "ipad",
60+
"scale" : "2x",
61+
"size" : "29x29"
62+
},
63+
{
64+
"idiom" : "ipad",
65+
"scale" : "1x",
66+
"size" : "40x40"
67+
},
68+
{
69+
"idiom" : "ipad",
70+
"scale" : "2x",
71+
"size" : "40x40"
72+
},
73+
{
74+
"idiom" : "ipad",
75+
"scale" : "1x",
76+
"size" : "76x76"
77+
},
78+
{
79+
"idiom" : "ipad",
80+
"scale" : "2x",
81+
"size" : "76x76"
82+
},
83+
{
84+
"idiom" : "ipad",
85+
"scale" : "2x",
86+
"size" : "83.5x83.5"
87+
},
88+
{
89+
"idiom" : "ios-marketing",
90+
"scale" : "1x",
91+
"size" : "1024x1024"
92+
}
93+
],
94+
"info" : {
95+
"author" : "xcode",
96+
"version" : 1
97+
}
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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>UIApplicationSceneManifest</key>
24+
<dict>
25+
<key>UIApplicationSupportsMultipleScenes</key>
26+
<true/>
27+
</dict>
28+
<key>UIApplicationSupportsIndirectInputEvents</key>
29+
<true/>
30+
<key>UILaunchScreen</key>
31+
<dict/>
32+
<key>UIRequiredDeviceCapabilities</key>
33+
<array>
34+
<string>armv7</string>
35+
</array>
36+
<key>UISupportedInterfaceOrientations</key>
37+
<array>
38+
<string>UIInterfaceOrientationPortrait</string>
39+
<string>UIInterfaceOrientationLandscapeLeft</string>
40+
<string>UIInterfaceOrientationLandscapeRight</string>
41+
</array>
42+
<key>UISupportedInterfaceOrientations~ipad</key>
43+
<array>
44+
<string>UIInterfaceOrientationPortrait</string>
45+
<string>UIInterfaceOrientationPortraitUpsideDown</string>
46+
<string>UIInterfaceOrientationLandscapeLeft</string>
47+
<string>UIInterfaceOrientationLandscapeRight</string>
48+
</array>
49+
</dict>
50+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Combine
2+
3+
protocol MenuFetching {
4+
5+
func fetchMenu() -> AnyPublisher<[MenuItem], Error>
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Combine
2+
import Foundation
3+
4+
class MenuFetchingPlaceholder: MenuFetching {
5+
func fetchMenu() -> AnyPublisher<[MenuItem], Error> {
6+
return Future { $0(.success(menu)) }
7+
// Use a delay to simulate async fetch
8+
.delay(for: 0.5, scheduler: RunLoop.main)
9+
.eraseToAnyPublisher()
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
func groupMenuByCategory(_ menu: [MenuItem]) -> [MenuSection] {
2+
guard menu.isEmpty == false else { return [] }
3+
4+
return Dictionary(grouping: menu, by: { $0.category })
5+
.map { key, value in MenuSection(category: key, items: value) }
6+
.sorted { $0.category > $1.category }
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
struct MenuItem {
2+
3+
let category: String
4+
let name: String
5+
let spicy: Bool
6+
let price: Double
7+
}
8+
9+
extension MenuItem: Identifiable {
10+
11+
var id: String { name }
12+
}
13+
14+
extension MenuItem: Equatable {}
15+
16+
extension MenuItem: Decodable {}

0 commit comments

Comments
 (0)